[ioemu] Update to qemu 0.90.
authorChristian Limpach <Christian.Limpach@xensource.com>
Wed, 9 May 2007 13:17:15 +0000 (14:17 +0100)
committerChristian Limpach <Christian.Limpach@xensource.com>
Wed, 9 May 2007 13:17:15 +0000 (14:17 +0100)
Signed-off-by: Christian Limpach <Christian.Limpach@xensource.com>
252 files changed:
tools/ioemu/.CVS/Entries
tools/ioemu/.CVS/Entries.Log [deleted file]
tools/ioemu/.CVS/Tag
tools/ioemu/.cvsignore
tools/ioemu/Changelog
tools/ioemu/LICENSE
tools/ioemu/Makefile
tools/ioemu/Makefile.target
tools/ioemu/README.distrib [deleted file]
tools/ioemu/VERSION
tools/ioemu/audio/.CVS/Entries
tools/ioemu/audio/.CVS/Tag
tools/ioemu/audio/wavaudio.c
tools/ioemu/audio/wavcapture.c
tools/ioemu/block-bochs.c
tools/ioemu/block-cloop.c
tools/ioemu/block-cow.c
tools/ioemu/block-dmg.c
tools/ioemu/block-qcow.c
tools/ioemu/block-qcow2.c [new file with mode: 0644]
tools/ioemu/block-raw.c [new file with mode: 0644]
tools/ioemu/block-vmdk.c
tools/ioemu/block-vpc.c
tools/ioemu/block-vvfat.c
tools/ioemu/block.c
tools/ioemu/block_int.h
tools/ioemu/check_ops.sh [new file with mode: 0755]
tools/ioemu/configure
tools/ioemu/console.c
tools/ioemu/cpu-all.h
tools/ioemu/cpu-defs.h
tools/ioemu/cpu-exec.c
tools/ioemu/cutils.c [new file with mode: 0644]
tools/ioemu/disas.c
tools/ioemu/dyngen-exec.h
tools/ioemu/dyngen.c
tools/ioemu/dyngen.h
tools/ioemu/elf.h
tools/ioemu/elf_ops.h
tools/ioemu/exec-all.h
tools/ioemu/exec.c
tools/ioemu/fpu/.CVS/Entries
tools/ioemu/fpu/.CVS/Tag
tools/ioemu/fpu/softfloat-native.c
tools/ioemu/fpu/softfloat-native.h
tools/ioemu/fpu/softfloat-specialize.h
tools/ioemu/fpu/softfloat.c
tools/ioemu/fpu/softfloat.h
tools/ioemu/gdbstub.c
tools/ioemu/gdbstub.h
tools/ioemu/hostregs_helper.h [new file with mode: 0644]
tools/ioemu/hw/.CVS/Entries
tools/ioemu/hw/.CVS/Tag
tools/ioemu/hw/acpi-dsdt.dsl [deleted file]
tools/ioemu/hw/acpi-dsdt.hex [deleted file]
tools/ioemu/hw/acpi.c
tools/ioemu/hw/adb.c
tools/ioemu/hw/apb_pci.c
tools/ioemu/hw/apic.c
tools/ioemu/hw/arm_boot.c
tools/ioemu/hw/arm_gic.c [new file with mode: 0644]
tools/ioemu/hw/arm_sysctl.c [new file with mode: 0644]
tools/ioemu/hw/arm_timer.c
tools/ioemu/hw/cirrus_vga.c
tools/ioemu/hw/cs4231.c [new file with mode: 0644]
tools/ioemu/hw/esp.c
tools/ioemu/hw/fdc.c
tools/ioemu/hw/grackle_pci.c
tools/ioemu/hw/gt64xxx.c [new file with mode: 0644]
tools/ioemu/hw/i8259.c
tools/ioemu/hw/ide.c
tools/ioemu/hw/integratorcp.c
tools/ioemu/hw/iommu.c
tools/ioemu/hw/isa_mmio.c [new file with mode: 0644]
tools/ioemu/hw/lance.c [deleted file]
tools/ioemu/hw/lsi53c895a.c
tools/ioemu/hw/mc146818rtc.c
tools/ioemu/hw/mips_int.c [new file with mode: 0644]
tools/ioemu/hw/mips_malta.c [new file with mode: 0644]
tools/ioemu/hw/mips_r4k.c
tools/ioemu/hw/mips_timer.c [new file with mode: 0644]
tools/ioemu/hw/ne2000.c
tools/ioemu/hw/pc.c
tools/ioemu/hw/pci.c
tools/ioemu/hw/pcnet.c
tools/ioemu/hw/pflash_cfi02.c
tools/ioemu/hw/piix4acpi.c
tools/ioemu/hw/piix_pci.c
tools/ioemu/hw/pl011.c
tools/ioemu/hw/pl080.c
tools/ioemu/hw/pl110.c
tools/ioemu/hw/pl110_template.h
tools/ioemu/hw/ppc.c
tools/ioemu/hw/ppc_chrp.c
tools/ioemu/hw/ppc_prep.c
tools/ioemu/hw/prep_pci.c
tools/ioemu/hw/ps2.c
tools/ioemu/hw/realview.c [new file with mode: 0644]
tools/ioemu/hw/rtl8139.c
tools/ioemu/hw/scsi-disk.c
tools/ioemu/hw/serial.c
tools/ioemu/hw/sh7750.c
tools/ioemu/hw/slavio_misc.c
tools/ioemu/hw/slavio_serial.c
tools/ioemu/hw/smbus.h [new file with mode: 0644]
tools/ioemu/hw/smbus_eeprom.c [new file with mode: 0644]
tools/ioemu/hw/smc91c111.c
tools/ioemu/hw/sparc32_dma.c [new file with mode: 0644]
tools/ioemu/hw/sun4m.c
tools/ioemu/hw/sun4u.c
tools/ioemu/hw/tcx.c
tools/ioemu/hw/unin_pci.c
tools/ioemu/hw/usb-hid.c
tools/ioemu/hw/usb-hub.c
tools/ioemu/hw/usb-msd.c
tools/ioemu/hw/usb-ohci.c
tools/ioemu/hw/usb-uhci.c
tools/ioemu/hw/usb.c
tools/ioemu/hw/usb.h
tools/ioemu/hw/versatile_pci.c
tools/ioemu/hw/versatilepb.c
tools/ioemu/hw/vga.c
tools/ioemu/hw/vga_int.h
tools/ioemu/hw/xen_platform.c
tools/ioemu/keymaps.c
tools/ioemu/keymaps/.CVS/Entries
tools/ioemu/keymaps/.CVS/Tag
tools/ioemu/keymaps/ja
tools/ioemu/kqemu.c
tools/ioemu/loader.c
tools/ioemu/monitor.c
tools/ioemu/osdep.c
tools/ioemu/osdep.h
tools/ioemu/patches/acpi-poweroff-support
tools/ioemu/patches/acpi-support
tools/ioemu/patches/acpi-timer-support
tools/ioemu/patches/domain-destroy
tools/ioemu/patches/domain-reset
tools/ioemu/patches/domain-timeoffset
tools/ioemu/patches/fix-interrupt-routing
tools/ioemu/patches/fix-vga-scanning-code-overflow
tools/ioemu/patches/hypervisor-pit
tools/ioemu/patches/hypervisor-rtc
tools/ioemu/patches/ide-error-reporting
tools/ioemu/patches/ioemu-buffer-pio-ia64
tools/ioemu/patches/ioemu-ia64
tools/ioemu/patches/ioemu-save-restore
tools/ioemu/patches/ioemu-save-restore-acpi
tools/ioemu/patches/ioemu-save-restore-ide
tools/ioemu/patches/ioemu-save-restore-logdirty
tools/ioemu/patches/ioemu-save-restore-ne2000
tools/ioemu/patches/ioemu-save-restore-pcnet
tools/ioemu/patches/ioemu-save-restore-rtl8139
tools/ioemu/patches/ioemu-save-restore-timer
tools/ioemu/patches/ioemu-save-restore-usb
tools/ioemu/patches/ne2000-bounds-checks
tools/ioemu/patches/qemu-64bit
tools/ioemu/patches/qemu-allow-disable-sdl
tools/ioemu/patches/qemu-block-device-bounds-checks
tools/ioemu/patches/qemu-bootorder
tools/ioemu/patches/qemu-bugfixes
tools/ioemu/patches/qemu-cirrus-bounds-checks
tools/ioemu/patches/qemu-cleanup
tools/ioemu/patches/qemu-daemonize
tools/ioemu/patches/qemu-dm
tools/ioemu/patches/qemu-dma-null-pointer-check
tools/ioemu/patches/qemu-hvm-banner
tools/ioemu/patches/qemu-infrastructure
tools/ioemu/patches/qemu-init-vgabios
tools/ioemu/patches/qemu-logging
tools/ioemu/patches/qemu-no-apic
tools/ioemu/patches/qemu-nobios
tools/ioemu/patches/qemu-pci
tools/ioemu/patches/qemu-pci-vendor-ids
tools/ioemu/patches/qemu-serial-fixes
tools/ioemu/patches/qemu-smp
tools/ioemu/patches/qemu-target-i386-dm
tools/ioemu/patches/qemu-timer
tools/ioemu/patches/qemu-tunable-ide-write-cache
tools/ioemu/patches/remove-pci-bridge-setup
tools/ioemu/patches/rtl8139-bound-chaining
tools/ioemu/patches/scsi
tools/ioemu/patches/serial-non-block
tools/ioemu/patches/serial-port-rate-limit
tools/ioemu/patches/series
tools/ioemu/patches/shadow-vram
tools/ioemu/patches/shared-vram
tools/ioemu/patches/support-xm-console
tools/ioemu/patches/tpm-tis-device
tools/ioemu/patches/usb-mouse-tablet-status-check
tools/ioemu/patches/vnc-access-monitor-vt
tools/ioemu/patches/vnc-backoff-screen-scan
tools/ioemu/patches/vnc-cleanup
tools/ioemu/patches/vnc-display-find-unused
tools/ioemu/patches/vnc-fix-signedness
tools/ioemu/patches/vnc-fix-version-check
tools/ioemu/patches/vnc-fixes
tools/ioemu/patches/vnc-listen-specific-interface
tools/ioemu/patches/vnc-password
tools/ioemu/patches/vnc-protocol-fixes
tools/ioemu/patches/vnc-start-vncviewer
tools/ioemu/patches/vnc-title-domain-name
tools/ioemu/patches/xen-build
tools/ioemu/patches/xen-domain-name
tools/ioemu/patches/xen-domid
tools/ioemu/patches/xen-mapcache
tools/ioemu/patches/xen-mm
tools/ioemu/patches/xen-network
tools/ioemu/patches/xen-platform-device
tools/ioemu/patches/xen-support-buffered-ioreqs
tools/ioemu/patches/xenstore
tools/ioemu/patches/xenstore-block-device-config
tools/ioemu/patches/xenstore-device-info-functions
tools/ioemu/patches/xenstore-write-vnc-port
tools/ioemu/pc-bios/.CVS/Entries
tools/ioemu/pc-bios/.CVS/Tag
tools/ioemu/pc-bios/README
tools/ioemu/pc-bios/bios.diff
tools/ioemu/pc-bios/pxe-ne2k_pci.bin [new file with mode: 0644]
tools/ioemu/pc-bios/pxe-pcnet.bin [new file with mode: 0644]
tools/ioemu/pc-bios/pxe-rtl8139.bin [new file with mode: 0644]
tools/ioemu/qemu-doc.texi
tools/ioemu/qemu-img.c
tools/ioemu/qemu-img.texi
tools/ioemu/qemu_socket.h
tools/ioemu/sdl.c
tools/ioemu/tap-win32.c
tools/ioemu/target-i386-dm/helper2.c
tools/ioemu/target-i386-dm/piix_pci-dm.c
tools/ioemu/target-i386-dm/rtc-dm.c
tools/ioemu/target-i386/.CVS/Entries
tools/ioemu/target-i386/.CVS/Tag
tools/ioemu/target-i386/cpu.h
tools/ioemu/target-i386/exec.h
tools/ioemu/target-i386/helper.c
tools/ioemu/target-i386/helper2.c
tools/ioemu/target-i386/op.c
tools/ioemu/target-i386/ops_sse.h
tools/ioemu/target-i386/translate.c
tools/ioemu/tests/.CVS/Entries
tools/ioemu/tests/.CVS/Tag
tools/ioemu/tests/Makefile
tools/ioemu/tests/hello-mips.c [new file with mode: 0644]
tools/ioemu/tests/test-i386.c
tools/ioemu/translate-all.c
tools/ioemu/usb-linux.c
tools/ioemu/vl.c
tools/ioemu/vl.h
tools/ioemu/vnc.c
tools/ioemu/vnc_keysym.h
tools/ioemu/vnchextile.h
tools/ioemu/x_keymap.c [new file with mode: 0644]

index 1e081de4851586ef4b7465e47732ee87273f61f7..a13b39b05e8c73a316194fa5ed372d377b5a5ca4 100644 (file)
 D/audio////
 D/hw////
-D/linux-user////
 D/pc-bios////
-D/slirp////
-D/target-arm////
 D/target-i386////
-D/target-ppc////
-D/target-sparc////
 D/tests////
 D/fpu////
 D/keymaps////
+/.cvsignore/1.16/Thu May  3 17:17:53 2007//Trelease_0_9_0
+/COPYING/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
+/COPYING.LIB/1.2/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
+/Changelog/1.128/Thu May  3 17:17:53 2007//Trelease_0_9_0
+/LICENSE/1.3/Thu May  3 17:17:53 2007//Trelease_0_9_0
+/Makefile/1.112/Thu May  3 17:17:53 2007//Trelease_0_9_0
+/Makefile.target/1.144/Thu May  3 17:17:53 2007//Trelease_0_9_0
+/README/1.12/Wed Oct 18 10:11:20 2006//Trelease_0_9_0
+/TODO/1.39/Fri Jan  5 14:34:35 2007//Trelease_0_9_0
+/VERSION/1.30/Thu May  3 17:17:53 2007//Trelease_0_9_0
+/a.out.h/1.2/Wed Oct 18 10:11:20 2006//Trelease_0_9_0
+/aes.c/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
+/aes.h/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
+/alpha-dis.c/1.3/Thu May  3 17:17:54 2007//Trelease_0_9_0
+/alpha.ld/1.1/Thu May  3 17:17:54 2007//Trelease_0_9_0
+/arm-dis.c/1.3/Thu May  3 17:17:54 2007//Trelease_0_9_0
+/arm-semi.c/1.2/Sun Jan 28 03:10:55 2007//Trelease_0_9_0
+/arm.ld/1.2/Thu May  3 17:17:54 2007//Trelease_0_9_0
+/block-bochs.c/1.3/Thu May  3 17:17:54 2007//Trelease_0_9_0
+/block-cloop.c/1.4/Thu May  3 17:17:54 2007//Trelease_0_9_0
+/block-cow.c/1.7/Thu May  3 17:17:54 2007//Trelease_0_9_0
+/block-dmg.c/1.5/Thu May  3 17:17:54 2007//Trelease_0_9_0
+/block-qcow.c/1.11/Thu May  3 17:17:54 2007//Trelease_0_9_0
+/block-qcow2.c/1.4/Mon Aug  7 02:38:06 2006//Trelease_0_9_0
+/block-raw.c/1.17/Thu Jan 18 00:22:11 2007//Trelease_0_9_0
+/block-vmdk.c/1.10/Thu May  3 17:17:55 2007//Trelease_0_9_0
+/block-vpc.c/1.4/Thu May  3 17:17:55 2007//Trelease_0_9_0
+/block-vvfat.c/1.8/Thu May  3 17:17:55 2007//Trelease_0_9_0
+/block.c/1.42/Thu May  3 17:17:55 2007//Trelease_0_9_0
+/block_int.h/1.10/Thu May  3 17:17:55 2007//Trelease_0_9_0
+/bswap.h/1.5/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
+/check_ops.sh/1.1/Sun Jan  7 19:38:08 2007//Trelease_0_9_0
+/cocoa.m/1.10/Fri Jan  5 14:34:35 2007//Trelease_0_9_0
+/configure/1.120/Thu May  3 17:17:55 2007//Trelease_0_9_0
+/console.c/1.11/Thu May  3 17:17:55 2007//Trelease_0_9_0
+/cpu-all.h/1.60/Thu May  3 17:17:55 2007//Trelease_0_9_0
+/cpu-defs.h/1.17/Thu May  3 17:17:55 2007//Trelease_0_9_0
+/cpu-exec.c/1.93/Thu May  3 17:17:55 2007//Trelease_0_9_0
+/cutils.c/1.1/Sun Jan  7 22:04:40 2007//Trelease_0_9_0
+/dis-asm.h/1.11/Wed Oct 18 10:11:20 2006//Trelease_0_9_0
+/disas.c/1.34/Thu May  3 17:17:55 2007//Trelease_0_9_0
+/disas.h/1.7/Thu May  3 17:17:36 2007//Trelease_0_9_0
+/dyngen-exec.h/1.31/Thu May  3 17:17:55 2007//Trelease_0_9_0
+/dyngen-op.h/1.1/Wed Oct 18 10:11:20 2006//Trelease_0_9_0
+/dyngen.c/1.47/Thu May  3 17:17:55 2007//Trelease_0_9_0
+/dyngen.h/1.12/Thu May  3 17:17:55 2007//Trelease_0_9_0
+/elf.h/1.8/Thu May  3 17:17:55 2007//Trelease_0_9_0
+/elf_ops.h/1.5/Thu May  3 17:17:55 2007//Trelease_0_9_0
+/exec-all.h/1.49/Thu May  3 17:17:55 2007//Trelease_0_9_0
+/exec.c/1.85/Thu May  3 17:17:55 2007//Trelease_0_9_0
+/gdbstub.c/1.47/Thu May  3 17:17:55 2007//Trelease_0_9_0
+/gdbstub.h/1.5/Thu May  3 17:17:55 2007//Trelease_0_9_0
+/hostregs_helper.h/1.1/Sun Feb  4 13:37:44 2007//Trelease_0_9_0
+/i386-dis.c/1.5/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/i386-vl.ld/1.3/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/i386.ld/1.2/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/ia64.ld/1.1/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/keymaps.c/1.2/Thu May  3 17:17:34 2007//Trelease_0_9_0
+/kqemu.c/1.15/Thu May  3 17:17:55 2007//Trelease_0_9_0
+/kqemu.h/1.1/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/loader.c/1.4/Thu May  3 17:17:55 2007//Trelease_0_9_0
+/m68k-dis.c/1.1/Thu May  3 17:17:56 2007//Trelease_0_9_0
+/m68k.ld/1.1/Thu May  3 17:17:56 2007//Trelease_0_9_0
+/mips-dis.c/1.4/Thu May  3 17:17:57 2007//Trelease_0_9_0
+/monitor.c/1.64/Thu May  3 17:17:57 2007//Trelease_0_9_0
+/osdep.c/1.15/Thu May  3 17:17:57 2007//Trelease_0_9_0
+/osdep.h/1.8/Thu May  3 17:17:57 2007//Trelease_0_9_0
+/ppc-dis.c/1.7/Thu May  3 17:17:58 2007//Trelease_0_9_0
+/ppc.ld/1.2/Thu May  3 17:17:58 2007//Trelease_0_9_0
+/qemu-binfmt-conf.sh/1.4/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/qemu-doc.texi/1.128/Thu May  3 17:17:58 2007//Trelease_0_9_0
+/qemu-img.c/1.16/Thu May  3 17:17:58 2007//Trelease_0_9_0
+/qemu-img.texi/1.3/Thu May  3 17:17:58 2007//Trelease_0_9_0
+/qemu-tech.texi/1.9/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/qemu_socket.h/1.2/Thu May  3 17:17:58 2007//Trelease_0_9_0
+/readline.c/1.1/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/s390.ld/1.1/Thu May  3 17:17:58 2007//Trelease_0_9_0
+/sdl.c/1.34/Thu May  3 17:17:58 2007//Trelease_0_9_0
+/sdl_keysym.h/1.3/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/sh4-dis.c/1.1/Thu May  3 17:17:58 2007//Trelease_0_9_0
+/softmmu_exec.h/1.1/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/softmmu_header.h/1.13/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/softmmu_template.h/1.16/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/sparc-dis.c/1.3/Thu May  3 17:17:59 2007//Trelease_0_9_0
+/sparc.ld/1.1/Thu May  3 17:17:59 2007//Trelease_0_9_0
+/sparc64.ld/1.1/Fri Aug  4 21:55:15 2006//Trelease_0_9_0
+/tap-win32.c/1.4/Thu May  3 17:17:59 2007//Trelease_0_9_0
+/texi2pod.pl/1.1/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/thunk.c/1.6/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/thunk.h/1.13/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
+/translate-all.c/1.15/Thu May  3 17:17:59 2007//Trelease_0_9_0
+/translate-op.c/1.1/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/usb-linux.c/1.10/Thu May  3 17:17:59 2007//Trelease_0_9_0
+/vgafont.h/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
+/vl.c/1.248/Thu May  3 17:17:59 2007//Trelease_0_9_0
+/vl.h/1.184/Thu May  3 17:17:59 2007//Trelease_0_9_0
+/vnc.c/1.12/Thu May  3 17:17:59 2007//Trelease_0_9_0
+/vnc_keysym.h/1.2/Thu May  3 17:17:59 2007//Trelease_0_9_0
+/vnchextile.h/1.3/Thu May  3 17:17:59 2007//Trelease_0_9_0
+/x86_64.ld/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
+/x_keymap.c/1.1/Wed Jan 24 21:40:21 2007//Trelease_0_9_0
+D/darwin-user////
+D/linux-user////
+D/slirp////
+D/target-arm////
+D/target-m68k////
 D/target-mips////
+D/target-ppc////
 D/target-sh4////
-/.cvsignore/1.14/Sun Aug  6 01:03:44 2006//Trelease_0_8_2
-/COPYING/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/COPYING.LIB/1.2/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/Changelog/1.121/Sun Aug  6 01:03:44 2006//Trelease_0_8_2
-/LICENSE/1.2/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/Makefile/1.104/Sun Aug  6 01:03:44 2006//Trelease_0_8_2
-/Makefile.target/1.121/Sun Aug  6 01:03:44 2006//Trelease_0_8_2
-/README/1.12/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/README.distrib/1.2/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/TODO/1.39/Sun Aug  6 01:03:44 2006//Trelease_0_8_2
-/VERSION/1.29/Sun Aug  6 01:03:44 2006//Trelease_0_8_2
-/a.out.h/1.2/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/aes.c/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/aes.h/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/alpha-dis.c/1.3/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
-/alpha.ld/1.1/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
-/arm-dis.c/1.3/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
-/arm.ld/1.1/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
-/block-bochs.c/1.1/Sun Aug  6 00:55:02 2006//Trelease_0_8_2
-/block-cloop.c/1.3/Sun Aug  6 00:55:02 2006//Trelease_0_8_2
-/block-cow.c/1.6/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
-/block-dmg.c/1.4/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/block-qcow.c/1.7/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
-/block-vmdk.c/1.8/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
-/block-vpc.c/1.3/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
-/block-vvfat.c/1.6/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
-/block.c/1.28/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
-/block_int.h/1.5/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
-/bswap.h/1.5/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/cocoa.m/1.10/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
-/configure/1.110/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
-/console.c/1.8/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
-/cpu-all.h/1.57/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
-/cpu-defs.h/1.16/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
-/cpu-exec.c/1.83/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
-/dis-asm.h/1.11/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/disas.c/1.31/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
-/disas.h/1.7/Sun Aug  6 00:55:03 2006//Trelease_0_8_2
-/dyngen-exec.h/1.29/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
-/dyngen-op.h/1.1/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/dyngen.c/1.45/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
-/dyngen.h/1.11/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
-/elf.h/1.7/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
-/elf_ops.h/1.3/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/exec-all.h/1.48/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
-/exec.c/1.82/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
-/gdbstub.c/1.40/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
-/gdbstub.h/1.2/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/i386-dis.c/1.5/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/i386-vl.ld/1.3/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/i386.ld/1.2/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/ia64.ld/1.1/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/keymaps.c/1.2/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/kqemu.c/1.12/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
-/kqemu.h/1.1/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/linux-2.6.9-qemu-fast.patch/1.1/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
-/loader.c/1.3/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
-/m68k-dis.c/1.1/Sun Aug  6 01:03:46 2006//Trelease_0_8_2
-/m68k.ld/1.1/Sun Aug  6 01:03:46 2006//Trelease_0_8_2
-/mips-dis.c/1.4/Sun Aug  6 01:03:47 2006//Trelease_0_8_2
-/monitor.c/1.54/Sun Aug  6 01:03:47 2006//Trelease_0_8_2
-/osdep.c/1.11/Sun Aug  6 01:03:47 2006//Trelease_0_8_2
-/osdep.h/1.6/Sun Aug  6 01:03:47 2006//Trelease_0_8_2
-/ppc-dis.c/1.7/Sun Aug  6 01:03:48 2006//Trelease_0_8_2
-/ppc.ld/1.2/Sun Aug  6 01:03:48 2006//Trelease_0_8_2
-/qemu-binfmt-conf.sh/1.4/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
-/qemu-doc.texi/1.100/Sun Aug  6 01:03:48 2006//Trelease_0_8_2
-/qemu-img.c/1.10/Sun Aug  6 01:03:48 2006//Trelease_0_8_2
-/qemu-img.texi/1.2/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
-/qemu-tech.texi/1.9/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
-/qemu_socket.h/1.1/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
-/readline.c/1.1/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
-/s390.ld/1.1/Sun Aug  6 01:03:48 2006//Trelease_0_8_2
-/sdl.c/1.29/Sun Aug  6 01:03:48 2006//Trelease_0_8_2
-/sdl_keysym.h/1.3/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
-/sh4-dis.c/1.1/Sun Aug  6 01:03:48 2006//Trelease_0_8_2
-/softmmu_exec.h/1.1/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
-/softmmu_header.h/1.13/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
-/softmmu_template.h/1.16/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
-/sparc-dis.c/1.3/Sun Aug  6 01:03:49 2006//Trelease_0_8_2
-/sparc.ld/1.1/Sun Aug  6 01:03:49 2006//Trelease_0_8_2
-/tap-win32.c/1.3/Sun Aug  6 01:03:49 2006//Trelease_0_8_2
-/texi2pod.pl/1.1/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
-/thunk.c/1.6/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
-/thunk.h/1.13/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/translate-all.c/1.14/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
-/translate-op.c/1.1/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
-/usb-linux.c/1.8/Sun Aug  6 01:03:49 2006//Trelease_0_8_2
-/vgafont.h/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/vl.c/1.202/Sun Aug  6 01:03:49 2006//Trelease_0_8_2
-/vl.h/1.136/Sun Aug  6 01:03:49 2006//Trelease_0_8_2
-/vnc.c/1.7/Sun Aug  6 01:03:49 2006//Trelease_0_8_2
-/vnc_keysym.h/1.1/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
-/vnchextile.h/1.2/Sun Aug  6 01:03:49 2006//Trelease_0_8_2
-/x86_64.ld/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
+D/target-sparc////
diff --git a/tools/ioemu/.CVS/Entries.Log b/tools/ioemu/.CVS/Entries.Log
deleted file mode 100644 (file)
index 45c50e1..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-A D/linux-user////
-A D/slirp////
-A D/target-arm////
-A D/target-mips////
-A D/target-ppc////
-A D/target-sh4////
-A D/target-sparc////
index bd48d406fa1b16a1721b34dc4bb6979acc4274da..eed9f4a4fb93e992c8c20b591822041f09711c7e 100644 (file)
@@ -1 +1 @@
-Nrelease_0_8_2
+Nrelease_0_9_0
index 7be41c433f927acf1f54f4703a3e7ce1c6758932..ae68e450c83e627062b30d0068a2962fa37697e0 100644 (file)
@@ -1,14 +1,16 @@
-arm-user
+arm-linux-user
 arm-softmmu
-armeb-user
+armeb-linux-user
 config-host.*
 dyngen
 i386
 i386-softmmu
-i386-user
+i386-darwin-user
+i386-linux-user
 ppc-softmmu
 ppc64-softmmu
-ppc-user
+ppc-darwin-user
+ppc-linux-user
 qemu-doc.html
 qemu-tech.html
 qemu-doc.info
@@ -17,18 +19,19 @@ qemu.1
 qemu.pod
 qemu-img.1
 qemu-img.pod
-sparc-user
+sparc-linux-user
 qemu-img
 sparc-softmmu
 x86_64-softmmu
-sparc64-user
+sparc64-linux-user
 sparc64-softmmu
 mips-softmmu
 mipsel-softmmu
-mips-user
-mipsel-user
+mips-linux-user
+mipsel-linux-user
+m68k-linux-user
 .gdbinit
-sh4-user
+sh4-linux-user
 sh4-softmmu
 *.aux
 *.cp
index 58f3e5e743d65dff17509dba648b6e0259d8a9a3..ea9ea7492f880a2566bc91f2f656f587d4780bbd 100644 (file)
@@ -1,3 +1,21 @@
+version 0.9.0:
+
+  - Support for relative paths in backing files for disk images
+  - Async file I/O API
+  - New qcow2 disk image format
+  - Support of multiple VM snapshots
+  - Linux: specific host CDROM and floppy support
+  - SMM support
+  - Moved PCI init, MP table init and ACPI table init to Bochs BIOS
+  - Support for MIPS32 Release 2 instruction set (Thiemo Seufer)
+  - MIPS Malta system emulation (Aurelien Jarno, Stefan Weil)
+  - Darwin userspace emulation (Pierre d'Herbemont)
+  - m68k user support (Paul Brook)
+  - several x86 and x86_64 emulation fixes
+  - Mouse relative offset VNC extension (Anthony Liguori)
+  - PXE boot support (Anthony Liguori)
+  - '-daemonize' option (Anthony Liguori)
+
 version 0.8.2:
 
   - ACPI support
index bfc9a1f4273b360009cc5419f5de8bee090a1adf..8bf5f94fadacda669baffa2b541394b5667ff930 100644 (file)
@@ -1,11 +1,14 @@
-The following points clarify the QEMU licenses:
+The following points clarify the QEMU license:
 
-1) The QEMU virtual CPU core library (libqemu.a) and the QEMU PC
-   system emulator are released under the GNU Lesser General Public
-   License.
+1) QEMU as a whole is released under the GNU General Public License
 
-2) The Linux user mode QEMU emulator is released under the GNU General
-   Public License.
+2) Parts of QEMU have specific licenses which are compatible with the
+GNU General Public License. Hence each source file contains its own
+licensing information.
+
+In particular, the QEMU virtual CPU core library (libqemu.a) is
+released under the GNU Lesser General Public License. Many hardware
+device emulation sources are released under the BSD license.
 
 3) QEMU is a trademark of Fabrice Bellard.
 
index 6333268289d72268d9c7aee0bfcfacc872ea7ce5..c676052e3cd2310bfcb8f957e9815739d5497479 100644 (file)
@@ -8,19 +8,18 @@ include $(XEN_ROOT)/tools/Rules.mk
 .PHONY: all clean distclean dvi info install install-doc tar tarbin \
        speed test test2 html dvi info
 
-CFLAGS+=-Wall -O2 -g -fno-strict-aliasing -I.
-ifdef CONFIG_DARWIN
-CFLAGS+= -mdynamic-no-pic
-endif
+BASE_CFLAGS=
+BASE_LDFLAGS=
+
+BASE_CFLAGS += $(OS_CFLAGS)
 ifeq ($(ARCH),sparc)
-CFLAGS+=-mcpu=ultrasparc
+BASE_CFLAGS += -mcpu=ultrasparc
 endif
-LDFLAGS=-g
+CPPFLAGS += -I. -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
 LIBS=
-DEFINES+=-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
 TOOLS=qemu-img$(EXESUF)
 ifdef CONFIG_STATIC
-LDFLAGS+=-static
+BASE_LDFLAGS += -static
 endif
 ifdef BUILD_DOCS
 DOCS=qemu-doc.html qemu-tech.html qemu.1 qemu-img.1
@@ -28,6 +27,14 @@ else
 DOCS=
 endif
 
+ifndef CONFIG_DARWIN
+ifndef CONFIG_WIN32
+ifndef CONFIG_SOLARIS
+LIBS+=-lrt
+endif
+endif
+endif
+
 TOOLS=
 
 all: $(TOOLS) $(DOCS) recurse-all
@@ -36,12 +43,12 @@ subdir-%:
        $(MAKE) -C $(subst subdir-,,$@) all
 
 recurse-all: $(patsubst %,subdir-%, $(TARGET_DIRS))
-        
-qemu-img$(EXESUF): qemu-img.c block.c block-cow.c block-qcow.c aes.c block-vmdk.c block-cloop.c block-dmg.c block-bochs.c block-vpc.c block-vvfat.c
-       $(CC) -DQEMU_TOOL $(CFLAGS) $(LDFLAGS) $(DEFINES) -o $@ $^ -lz $(LIBS)
+
+qemu-img$(EXESUF): qemu-img.c cutils.c block.c block-raw.c block-cow.c block-qcow.c aes.c block-vmdk.c block-cloop.c block-dmg.c block-bochs.c block-vpc.c block-vvfat.c block-qcow2.c
+       $(CC) -DQEMU_TOOL $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) $(LDFLAGS) $(BASE_LDFLAGS) -o $@ $^ -lz $(LIBS)
 
 dyngen$(EXESUF): dyngen.c
-       $(HOST_CC) $(CFLAGS) $(DEFINES) -o $@ $^
+       $(HOST_CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -o $@ $^
 
 clean:
 # avoid old build problems by removing potentially incorrect old files
@@ -65,7 +72,7 @@ common  de-ch  es     fo  fr-ca  hu     ja  mk  nl-be      pt  sl     tr
 
 install-doc: $(DOCS)
        mkdir -p "$(DESTDIR)$(docdir)"
-       $(INSTALL_DATA) qemu-doc.html  qemu-tech.html "$(DESTDIR)$(docdir)"
+       $(INSTALL_DATA) -m 644 qemu-doc.html  qemu-tech.html "$(DESTDIR)$(docdir)"
 ifndef CONFIG_WIN32
        mkdir -p "$(DESTDIR)$(mandir)/man1"
        $(INSTALL_DATA) qemu.1 qemu-img.1 "$(DESTDIR)$(mandir)/man1"
@@ -76,13 +83,14 @@ install: all $(if $(BUILD_DOCS),install-doc)
 #      $(INSTALL) -m 755 -s $(TOOLS) "$(DESTDIR)$(bindir)"
 #      mkdir -p "$(DESTDIR)$(datadir)"
 #      for x in bios.bin vgabios.bin vgabios-cirrus.bin ppc_rom.bin \
-#                      video.x openbios-sparc32 linux_boot.bin; do \
-#              $(INSTALL_DATA) $(SRC_PATH)/pc-bios/$$x "$(DESTDIR)$(datadir)"; \
+#              video.x openbios-sparc32 linux_boot.bin pxe-ne2k_pci.bin \
+#              pxe-rtl8139.bin pxe-pcnet.bin; do \
+#              $(INSTALL) -m 644 $(SRC_PATH)/pc-bios/$$x "$(DESTDIR)$(datadir)"; \
 #      done
 ifndef CONFIG_WIN32
        mkdir -p "$(DESTDIR)$(datadir)/keymaps"
        for x in $(KEYMAPS); do \
-               $(INSTALL_DATA) $(SRC_PATH)/keymaps/$$x "$(DESTDIR)$(datadir)/keymaps"; \
+               $(INSTALL_DATA) -m 644 $(SRC_PATH)/keymaps/$$x "$(DESTDIR)$(datadir)/keymaps"; \
        done
 endif
        for d in $(TARGET_DIRS); do \
@@ -125,7 +133,8 @@ dvi: qemu-doc.dvi qemu-tech.dvi
 
 html: qemu-doc.html qemu-tech.html
 
-FILE=qemu-$(shell cat VERSION)
+VERSION ?= $(shell cat VERSION)
+FILE = qemu-$(VERSION)
 
 # tar release (use 'make -k tar' on a checkouted tree)
 tar:
@@ -159,6 +168,9 @@ tarbin:
        $(datadir)/video.x \
        $(datadir)/openbios-sparc32 \
        $(datadir)/linux_boot.bin \
+        $(datadir)/pxe-ne2k_pci.bin \
+       $(datadir)/pxe-rtl8139.bin \
+        $(datadir)/pxe-pcnet.bin \
        $(docdir)/qemu-doc.html \
        $(docdir)/qemu-tech.html \
        $(mandir)/man1/qemu.1 $(mandir)/man1/qemu-img.1 )
index 4872128d20da4288f9514a50978d10d1ca02bae8..6d11dea8e43c00ea7beeedf7609964d986a86ea3 100644 (file)
@@ -15,21 +15,24 @@ TARGET_BASE_ARCH:=sparc
 endif
 TARGET_PATH=$(SRC_PATH)/target-$(TARGET_BASE_ARCH)$(TARGET_SUB)
 VPATH=$(SRC_PATH):$(TARGET_PATH):$(SRC_PATH)/hw:$(SRC_PATH)/audio
-DEFINES=-I. -I.. -I$(TARGET_PATH) -I$(SRC_PATH)
-DEFINES+= -I$(XEN_ROOT)/tools/libxc
-DEFINES+= -I$(XEN_ROOT)/tools/xenstore
-ifdef CONFIG_USER_ONLY
+CPPFLAGS=-I. -I.. -I$(TARGET_PATH) -I$(SRC_PATH)
+CPPFLAGS+= -I$(XEN_ROOT)/tools/libxc
+CPPFLAGS+= -I$(XEN_ROOT)/tools/xenstore
+ifdef CONFIG_DARWIN_USER
+VPATH+=:$(SRC_PATH)/darwin-user
+CPPFLAGS+=-I$(SRC_PATH)/darwin-user -I$(SRC_PATH)/darwin-user/$(TARGET_ARCH)
+endif
+ifdef CONFIG_LINUX_USER
 VPATH+=:$(SRC_PATH)/linux-user
-DEFINES+=-I$(SRC_PATH)/linux-user -I$(SRC_PATH)/linux-user/$(TARGET_ARCH)
+CPPFLAGS+=-I$(SRC_PATH)/linux-user -I$(SRC_PATH)/linux-user/$(TARGET_ARCH)
 endif
-CFLAGS+=-Wall -O2 -g -fno-strict-aliasing
+BASE_CFLAGS=
+BASE_LDFLAGS=
 SSE2 := $(call cc-option,$(CC),-msse2,)
 ifeq ($(SSE2),-msse2)
 CFLAGS += -DUSE_SSE2=1 -msse2
 endif
-CFLAGS+= $(LOCAL_CFLAGS)
 #CFLAGS+=-Werror
-LDFLAGS=-g
 LIBS=
 HELPER_CFLAGS=$(CFLAGS)
 DYNGEN=../dyngen$(EXESUF)
@@ -74,18 +77,20 @@ endif
 endif # !CONFIG_USER_ONLY
 
 ifdef CONFIG_STATIC
-LDFLAGS+=-static
+BASE_LDFLAGS+=-static
 endif
 
+# We require -O2 to avoid the stack setup prologue in EXIT_TB
+OP_CFLAGS = -Wall -O2 -g -fno-strict-aliasing
+
 ifeq ($(ARCH),i386)
-CFLAGS+=-fomit-frame-pointer
-OP_CFLAGS=$(CFLAGS) -mpreferred-stack-boundary=2
+HELPER_CFLAGS+=-fomit-frame-pointer
+OP_CFLAGS+=-mpreferred-stack-boundary=2 -fomit-frame-pointer
 ifeq ($(HAVE_GCC3_OPTIONS),yes)
 OP_CFLAGS+= -falign-functions=0 -fno-gcse
 else
 OP_CFLAGS+= -malign-functions=0
 endif
-
 ifdef TARGET_GPROF
 USE_I386_LD=y
 endif
@@ -93,76 +98,80 @@ ifdef CONFIG_STATIC
 USE_I386_LD=y
 endif
 ifdef USE_I386_LD
-LDFLAGS+=-Wl,-T,$(SRC_PATH)/i386.ld
+BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
 else
+ifdef CONFIG_LINUX_USER
 # WARNING: this LDFLAGS is _very_ tricky : qemu is an ELF shared object
 # that the kernel ELF loader considers as an executable. I think this
 # is the simplest way to make it self virtualizable!
-LDFLAGS+=-Wl,-shared
+BASE_LDFLAGS+=-Wl,-shared
+endif
 endif
 endif
 
 ifeq ($(ARCH),x86_64)
-OP_CFLAGS=$(CFLAGS) -falign-functions=0
-LDFLAGS+=-Wl,-T,$(SRC_PATH)/x86_64.ld
+BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
 endif
 
 ifeq ($(ARCH),ppc)
-CFLAGS+= -D__powerpc__
-OP_CFLAGS=$(CFLAGS)
-LDFLAGS+=-Wl,-T,$(SRC_PATH)/ppc.ld
+CPPFLAGS+= -D__powerpc__
+ifdef CONFIG_LINUX_USER
+BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
+endif
 endif
 
 ifeq ($(ARCH),s390)
-OP_CFLAGS=$(CFLAGS)
-LDFLAGS+=-Wl,-T,$(SRC_PATH)/s390.ld
+BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
 endif
 
 ifeq ($(ARCH),sparc)
 ifeq ($(CONFIG_SOLARIS),yes)
-CFLAGS+=-mcpu=ultrasparc -m32 -ffixed-g2 -ffixed-g3
-LDFLAGS+=-m32
-OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -fno-omit-frame-pointer -ffixed-i0
+BASE_CFLAGS+=-mcpu=ultrasparc -m32 -ffixed-g2 -ffixed-g3
+BASE_LDFLAGS+=-m32
+OP_CFLAGS+=-fno-delayed-branch -fno-omit-frame-pointer -ffixed-i0
 else
-CFLAGS+=-mcpu=ultrasparc -m32 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6
-LDFLAGS+=-m32
-OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -ffixed-i0
+BASE_CFLAGS+=-mcpu=ultrasparc -m32 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6
+BASE_LDFLAGS+=-m32
+OP_CFLAGS+=-fno-delayed-branch -ffixed-i0
 HELPER_CFLAGS=$(CFLAGS) -ffixed-i0 -mflat
 # -static is used to avoid g1/g3 usage by the dynamic linker
-LDFLAGS+=-Wl,-T,$(SRC_PATH)/sparc.ld -static
+BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld -static
 endif
 endif
 
 ifeq ($(ARCH),sparc64)
-CFLAGS+=-mcpu=ultrasparc -m64 -ffixed-g1 -ffixed-g4 -ffixed-g5 -ffixed-g7
-LDFLAGS+=-m64
-LDFLAGS+=-Wl,-T,$(SRC_PATH)/sparc64.ld
-OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -ffixed-i0
+BASE_CFLAGS+=-mcpu=ultrasparc -m64 -ffixed-g1 -ffixed-g4 -ffixed-g5 -ffixed-g7
+BASE_LDFLAGS+=-m64
+BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
+OP_CFLAGS+=-mcpu=ultrasparc -m64 -ffixed-g1 -ffixed-g4 -ffixed-g5 -ffixed-g7 -fno-delayed-branch -ffixed-i0
 endif
 
 ifeq ($(ARCH),alpha)
-# -msmall-data is not used because we want two-instruction relocations
-# for the constant constructions
-OP_CFLAGS=-Wall -O2 -g
+# -msmall-data is not used for OP_CFLAGS because we want two-instruction
+# relocations for the constant constructions
 # Ensure there's only a single GP
-CFLAGS += -msmall-data
-LDFLAGS+=-Wl,-T,$(SRC_PATH)/alpha.ld
+BASE_CFLAGS+=-msmall-data
+BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
 endif
 
 ifeq ($(ARCH),ia64)
-CFLAGS += -mno-sdata
-OP_CFLAGS=$(CFLAGS)
-LDFLAGS+=-Wl,-G0 -Wl,-T,$(SRC_PATH)/ia64.ld
+BASE_CFLAGS+=-mno-sdata
+OP_CFLAGS+=-mno-sdata
+BASE_LDFLAGS+=-Wl,-G0 -Wl,-T,$(SRC_PATH)/$(ARCH).ld
 endif
 
 ifeq ($(ARCH),arm)
-OP_CFLAGS=$(CFLAGS) -mno-sched-prolog -fno-omit-frame-pointer
-LDFLAGS+=-Wl,-T,$(SRC_PATH)/arm.ld
+OP_CFLAGS+=-mno-sched-prolog -fno-omit-frame-pointer
+BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
 endif
 
 ifeq ($(ARCH),m68k)
-OP_CFLAGS=$(CFLAGS) -fomit-frame-pointer
-LDFLAGS+=-Wl,-T,m68k.ld
+OP_CFLAGS+=-fomit-frame-pointer
+BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
+endif
+
+ifeq ($(ARCH),mips)
+BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
 endif
 
 ifeq ($(HAVE_GCC3_OPTIONS),yes)
@@ -171,14 +180,20 @@ OP_CFLAGS+=-fno-reorder-blocks -fno-optimize-sibling-calls
 endif
 
 ifeq ($(CONFIG_DARWIN),yes)
-OP_CFLAGS+= -mdynamic-no-pic
 LIBS+=-lmx
 endif
 
+ifdef CONFIG_DARWIN_USER
+# Leave some space for the regular program loading zone
+BASE_LDFLAGS+=-Wl,-segaddr,__STD_PROG_ZONE,0x1000 -image_base 0x0e000000
+endif
+
+OP_CFLAGS+=$(OS_CFLAGS)
+
 #########################################################
 
-DEFINES+=-D_GNU_SOURCE
-#-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
+CPPFLAGS+=-D_GNU_SOURCE
+# -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
 LIBS+=-lm
 LIBS+=-L../../libxc -lxenctrl -lxenguest
 LIBS+=-L../../xenstore -lxenstore
@@ -195,10 +210,11 @@ endif
 
 # profiling code
 ifdef TARGET_GPROF
-LDFLAGS+=-p
-main.o: CFLAGS+=-p
+BASE_LDFLAGS+=-p
+main.o: BASE_CFLAGS+=-p
 endif
 
+ifdef CONFIG_LINUX_USER
 OBJS= main.o syscall.o mmap.o signal.o path.o osdep.o thunk.o \
       elfload.o linuxload.o
 ifdef TARGET_HAS_BFLT
@@ -213,6 +229,15 @@ OBJS+=nwfpe/fpa11.o nwfpe/fpa11_cpdo.o \
 nwfpe/fpa11_cpdt.o nwfpe/fpa11_cprt.o nwfpe/fpopcode.o nwfpe/single_cpdo.o \
  nwfpe/double_cpdo.o nwfpe/extended_cpdo.o arm-semi.o
 endif
+ifeq ($(TARGET_ARCH), m68k)
+OBJS+= m68k-sim.o m68k-semi.o
+endif
+endif #CONFIG_LINUX_USER
+
+ifdef CONFIG_DARWIN_USER
+OBJS= main.o commpage.o machload.o mmap.o osdep.o signal.o syscall.o thunk.o
+endif
+
 SRCS:= $(OBJS:.o=.c)
 OBJS+= libqemu.a
 
@@ -224,7 +249,7 @@ LIBOBJS+=fpu/softfloat.o
 else
 LIBOBJS+=fpu/softfloat-native.o
 endif
-DEFINES+=-I$(SRC_PATH)/fpu
+CPPFLAGS+=-I$(SRC_PATH)/fpu
 
 ifeq ($(TARGET_ARCH), i386)
 LIBOBJS+=helper.o helper2.o
@@ -257,6 +282,10 @@ ifeq ($(TARGET_BASE_ARCH), sh4)
 LIBOBJS+= op_helper.o helper.o
 endif
 
+ifeq ($(TARGET_BASE_ARCH), m68k)
+LIBOBJS+= helper.o
+endif
+
 # NOTE: the disassembler code is only needed for debugging
 LIBOBJS+=disas.o 
 ifeq ($(findstring i386, $(TARGET_ARCH) $(ARCH)),i386)
@@ -304,7 +333,7 @@ endif
 all: $(PROGS)
 
 $(QEMU_USER): $(OBJS)
-       $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^  $(LIBS)
+       $(CC) $(CFLAGS) $(LDFLAGS) $(BASE_LDFLAGS) -o $@ $^  $(LIBS)
 ifeq ($(ARCH),alpha)
 # Mark as 32 bit binary, i. e. it will be mapped into the low 31 bit of
 # the address space (31 bit so sign extending doesn't matter)
@@ -312,8 +341,10 @@ ifeq ($(ARCH),alpha)
 endif
 
 # must use static linking to avoid leaving stuff in virtual address space
-VL_OBJS=vl.o osdep.o block.o readline.o monitor.o pci.o console.o
-VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o block-dmg.o block-bochs.o block-vpc.o block-vvfat.o
+VL_OBJS=vl.o osdep.o readline.o monitor.o pci.o console.o isa_mmio.o
+VL_OBJS+=cutils.o
+VL_OBJS+=block.o block-raw.o
+VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o block-dmg.o block-bochs.o block-vpc.o block-vvfat.o block-qcow2.o
 ifdef CONFIG_WIN32
 VL_OBJS+=tap-win32.o
 endif
@@ -339,7 +370,7 @@ LIBS += -lole32 -ldxguid
 endif
 ifdef CONFIG_FMOD
 AUDIODRV += fmodaudio.o
-audio.o fmodaudio.o: DEFINES := -I$(CONFIG_FMOD_INC) $(DEFINES)
+audio.o fmodaudio.o: CPPFLAGS := -I$(CONFIG_FMOD_INC) $(CPPFLAGS)
 LIBS += $(CONFIG_FMOD_LIB)
 endif
 ifdef CONFIG_ADLIB
@@ -365,23 +396,25 @@ else
 VL_OBJS+= fdc.o serial.o pc.o
 endif
 VL_OBJS+= cirrus_vga.o mixeng.o parallel.o acpi.o
-VL_OBJS+= usb-uhci.o
+VL_OBJS+= usb-uhci.o smbus_eeprom.o
 VL_OBJS+= piix4acpi.o
 VL_OBJS+= xenstore.o
 VL_OBJS+= xen_platform.o
 VL_OBJS+= tpm_tis.o
-DEFINES += -DHAS_AUDIO
+CPPFLAGS += -DHAS_AUDIO
 endif
 ifeq ($(TARGET_BASE_ARCH), ppc)
 VL_OBJS+= ppc.o ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
 VL_OBJS+= mc146818rtc.o serial.o i8259.o i8254.o fdc.o m48t59.o
 VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o heathrow_pic.o mixeng.o
 VL_OBJS+= grackle_pci.o prep_pci.o unin_pci.o
-DEFINES += -DHAS_AUDIO
+CPPFLAGS += -DHAS_AUDIO
 endif
 ifeq ($(TARGET_ARCH), mips)
-VL_OBJS+= mips_r4k.o dma.o vga.o serial.o i8254.o i8259.o
-#VL_OBJS+= #ide.o pckbd.o fdc.o m48t59.o
+VL_OBJS+= mips_r4k.o mips_malta.o mips_timer.o mips_int.o dma.o vga.o serial.o i8254.o i8259.o
+VL_OBJS+= ide.o gt64xxx.o pckbd.o ps2.o fdc.o mc146818rtc.o usb-uhci.o acpi.o
+VL_OBJS+= piix_pci.o parallel.o mixeng.o cirrus_vga.o $(SOUND_HW) $(AUDIODRV)
+DEFINES += -DHAS_AUDIO
 endif
 ifeq ($(TARGET_BASE_ARCH), sparc)
 ifeq ($(TARGET_ARCH), sparc64)
@@ -389,14 +422,17 @@ VL_OBJS+= sun4u.o ide.o pckbd.o ps2.o vga.o apb_pci.o
 VL_OBJS+= fdc.o mc146818rtc.o serial.o m48t59.o
 VL_OBJS+= cirrus_vga.o parallel.o
 else
-VL_OBJS+= sun4m.o tcx.o lance.o iommu.o m48t59.o slavio_intctl.o
-VL_OBJS+= slavio_timer.o slavio_serial.o slavio_misc.o fdc.o esp.o
+VL_OBJS+= sun4m.o tcx.o pcnet.o iommu.o m48t59.o slavio_intctl.o
+VL_OBJS+= slavio_timer.o slavio_serial.o slavio_misc.o fdc.o esp.o sparc32_dma.o
+VL_OBJS+= cs4231.o
 endif
 endif
 ifeq ($(TARGET_BASE_ARCH), arm)
 VL_OBJS+= integratorcp.o versatilepb.o ps2.o smc91c111.o arm_pic.o arm_timer.o
 VL_OBJS+= arm_boot.o pl011.o pl050.o pl080.o pl110.o pl190.o
 VL_OBJS+= versatile_pci.o
+VL_OBJS+= arm_gic.o realview.o arm_sysctl.o
+VL_OBJS+= arm-semi.o
 endif
 ifeq ($(TARGET_BASE_ARCH), sh4)
 VL_OBJS+= shix.o sh7750.o sh7750_regnames.o tc58128.o
@@ -405,7 +441,7 @@ ifdef CONFIG_GDBSTUB
 VL_OBJS+=gdbstub.o 
 endif
 ifdef CONFIG_SDL
-VL_OBJS+=sdl.o
+VL_OBJS+=sdl.o x_keymap.o
 endif
 VL_OBJS+=vnc.o
 VL_OBJS+=d3des.o
@@ -417,7 +453,7 @@ COCOA_LIBS+=-framework CoreAudio
 endif
 endif
 ifdef CONFIG_SLIRP
-DEFINES+=-I$(SRC_PATH)/slirp
+CPPFLAGS+=-I$(SRC_PATH)/slirp
 SLIRP_OBJS=cksum.o if.o ip_icmp.o ip_input.o ip_output.o \
 slirp.o mbuf.o misc.o sbuf.o socket.o tcp_input.o tcp_output.o \
 tcp_subr.o tcp_timer.o udp.o bootp.o debug.o tftp.o
@@ -440,7 +476,7 @@ endif
 endif
 endif
 ifdef TARGET_GPROF
-vl.o: CFLAGS+=-p
+vl.o: BASE_CFLAGS+=-p
 VL_LDFLAGS+=-p
 endif
 
@@ -461,25 +497,25 @@ $(QEMU_SYSTEM): $(VL_OBJS) libqemu.a
        $(CC) $(VL_LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(COCOA_LIBS) $(VL_LIBS)
 
 cocoa.o: cocoa.m
-       $(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
+       $(CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
 
 sdl.o: sdl.c keymaps.c sdl_keysym.h
-       $(CC) $(CFLAGS) $(DEFINES) $(SDL_CFLAGS) -c -o $@ $<
+       $(CC) $(CFLAGS) $(CPPFLAGS) $(SDL_CFLAGS) $(BASE_CFLAGS) -c -o $@ $<
 
 vnc.o: vnc.c keymaps.c sdl_keysym.h vnchextile.h
-       $(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
+       $(CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
 
 d3des.o: d3des.c d3des.h
        $(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
 
 sdlaudio.o: sdlaudio.c
-       $(CC) $(CFLAGS) $(DEFINES) $(SDL_CFLAGS) -c -o $@ $<
+       $(CC) $(CFLAGS) $(CPPFLAGS) $(SDL_CFLAGS) $(BASE_CFLAGS) -c -o $@ $<
 
 depend: $(SRCS)
-       $(CC) -MM $(CFLAGS) $(DEFINES) $^ 1>.depend
+       $(CC) -MM $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) $^ 1>.depend
 
 vldepend: $(VL_OBJS:.o=.c)
-       $(CC) -MM $(CFLAGS) $(DEFINES) $^ 1>.depend
+       $(CC) -MM $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) $^ 1>.depend
 
 # libqemu 
 
@@ -503,10 +539,26 @@ gen-op.h: op.o $(DYNGEN)
        $(DYNGEN) -g -o $@ $<
 
 op.o: op.c
-       $(CC) $(OP_CFLAGS) $(DEFINES) -c -o $@ $<
+       $(CC) $(OP_CFLAGS) $(CPPFLAGS) -c -o $@ $<
 
+# HELPER_CFLAGS is used for all the code compiled with static register
+# variables
+ifeq ($(TARGET_BASE_ARCH), i386)
+# XXX: rename helper.c to op_helper.c
 helper.o: helper.c
-       $(CC) $(HELPER_CFLAGS) $(DEFINES) -c -o $@ $<
+       $(CC) $(HELPER_CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
+else
+op_helper.o: op_helper.c
+       $(CC) $(HELPER_CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
+endif
+
+cpu-exec.o: cpu-exec.c
+       $(CC) $(HELPER_CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
+
+# Note: this is a workaround. The real fix is to avoid compiling
+# cpu_signal_handler() in cpu-exec.c.
+signal.o: signal.c
+       $(CC) $(HELPER_CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
 
 ifeq ($(TARGET_BASE_ARCH), i386)
 op.o: op.c opreg_template.h ops_template.h ops_template_mem.h ops_mem.h ops_sse.h
@@ -529,19 +581,12 @@ translate.o: translate.c translate_init.c
 endif
 
 ifeq ($(TARGET_ARCH), mips)
-op.o: op.c op_template.c op_mem.c
+op.o: op.c op_template.c fop_template.c op_mem.c
 op_helper.o: op_helper_mem.c
 endif
 
 loader.o: loader.c elf_ops.h
 
-acpi.o: acpi.c acpi-dsdt.hex
-
-ifdef BUILD_ACPI_TABLES
-$(SRC_PATH)/hw/acpi-dsdt.hex: acpi-dsdt.dsl
-       iasl -tc -p $@ $<
-endif
-
 ifeq ($(TARGET_ARCH), sh4)
 op.o: op.c op_mem.c cpu.h
 op_helper.o: op_helper.c exec.h cpu.h
@@ -555,10 +600,10 @@ endif
 $(OBJS) $(LIBOBJS) $(VL_OBJS): config.h ../config-host.h
 
 %.o: %.c
-       $(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
+       $(CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
 
 %.o: %.S
-       $(CC) $(DEFINES) -c -o $@ $<
+       $(CC) $(CPPFLAGS) -c -o $@ $<
 
 clean:
        rm -f *.o  *.a *~ $(PROGS) gen-op.h opc.h op.h nwfpe/*.o slirp/*.o fpu/*.o
diff --git a/tools/ioemu/README.distrib b/tools/ioemu/README.distrib
deleted file mode 100644 (file)
index a1598a2..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-Information about the various packages used to build the current qemu
-x86 binary distribution:
-
-* gcc 2.95.2 was used for the build. A glibc 2.1.3 Debian distribution
-  was used to get most of the binary packages.
-
-* wine-20020411 tarball
-
-  ./configure --prefix=/usr/local/wine-i386
-  
-  All exe and libs were stripped. Some compile time tools and the
-  includes were deleted.
-
-* ldconfig was launched to build the library links:
-
-  qemu-i386 /usr/gnemul/qemu-i386/bin/ldconfig-i386 -C /usr/gnemul/qemu-i386/etc/ld.so.cache
index 53a48a1e8c640f61bd1ad6dae1178602e97c7bfa..899f24fc754a14b89617093824d258aaa3aa2943 100644 (file)
@@ -1 +1 @@
-0.8.2
\ No newline at end of file
+0.9.0
\ No newline at end of file
index 7d60c0c65e34e2e135cb399857b20ee3de4d8322..5f39d877d6c3eab62f9761949e7cf4879b0b7f68 100644 (file)
@@ -1,20 +1,20 @@
-/alsaaudio.c/1.7/Sun Aug  6 01:03:49 2006//Trelease_0_8_2
-/audio.c/1.14/Sun Aug  6 01:03:50 2006//Trelease_0_8_2
-/audio.h/1.8/Sun Aug  6 01:03:50 2006//Trelease_0_8_2
-/audio_int.h/1.10/Sun Aug  6 01:03:50 2006//Trelease_0_8_2
-/audio_template.h/1.8/Sun Aug  6 01:03:50 2006//Trelease_0_8_2
-/coreaudio.c/1.7/Sun Aug  6 01:03:50 2006//Trelease_0_8_2
-/dsound_template.h/1.4/Sun Aug  6 01:03:50 2006//Trelease_0_8_2
-/dsoundaudio.c/1.3/Sun Aug  6 01:03:50 2006//Trelease_0_8_2
-/fmodaudio.c/1.7/Sun Aug  6 01:03:50 2006//Trelease_0_8_2
-/mixeng.c/1.4/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/mixeng.h/1.2/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/mixeng_template.h/1.2/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/noaudio.c/1.7/Sun Aug  6 01:03:50 2006//Trelease_0_8_2
-/ossaudio.c/1.11/Sun Aug  6 01:03:50 2006//Trelease_0_8_2
-/rate_template.h/1.3/Sun Aug  6 01:03:50 2006//Trelease_0_8_2
-/sdlaudio.c/1.8/Sun Aug  6 01:03:50 2006//Trelease_0_8_2
-/sys-queue.h/1.1/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/wavaudio.c/1.8/Sun Aug  6 01:03:50 2006//Trelease_0_8_2
-/wavcapture.c/1.5/Sat Jul 22 17:06:44 2006//Trelease_0_8_2
+/alsaaudio.c/1.7/Fri Jan  5 14:34:35 2007//Trelease_0_9_0
+/audio.c/1.15/Thu May  3 17:17:59 2007//Trelease_0_9_0
+/audio.h/1.8/Fri Jan  5 14:34:35 2007//Trelease_0_9_0
+/audio_int.h/1.10/Fri Jan  5 14:34:35 2007//Trelease_0_9_0
+/audio_template.h/1.8/Fri Jan  5 14:34:35 2007//Trelease_0_9_0
+/coreaudio.c/1.7/Fri Jan  5 14:34:35 2007//Trelease_0_9_0
+/dsound_template.h/1.4/Fri Jan  5 14:34:35 2007//Trelease_0_9_0
+/dsoundaudio.c/1.3/Fri Jan  5 14:34:35 2007//Trelease_0_9_0
+/fmodaudio.c/1.7/Fri Jan  5 14:34:35 2007//Trelease_0_9_0
+/mixeng.c/1.4/Wed Oct 18 10:11:20 2006//Trelease_0_9_0
+/mixeng.h/1.2/Wed Oct 18 10:11:20 2006//Trelease_0_9_0
+/mixeng_template.h/1.2/Wed Oct 18 10:11:20 2006//Trelease_0_9_0
+/noaudio.c/1.7/Fri Jan  5 14:34:35 2007//Trelease_0_9_0
+/ossaudio.c/1.11/Fri Jan  5 14:34:35 2007//Trelease_0_9_0
+/rate_template.h/1.3/Fri Jan  5 14:34:35 2007//Trelease_0_9_0
+/sdlaudio.c/1.8/Fri Jan  5 14:34:35 2007//Trelease_0_9_0
+/sys-queue.h/1.1/Wed Oct 18 10:11:20 2006//Trelease_0_9_0
+/wavaudio.c/1.9/Thu May  3 17:17:59 2007//Trelease_0_9_0
+/wavcapture.c/1.7/Thu May  3 17:17:59 2007//Trelease_0_9_0
 D
index bd48d406fa1b16a1721b34dc4bb6979acc4274da..eed9f4a4fb93e992c8c20b591822041f09711c7e 100644 (file)
@@ -1 +1 @@
-Nrelease_0_8_2
+Nrelease_0_9_0
index c359fc4f2b98b22869fb6d034d8955d162101844..a552b7e973730232a238296157bc77da0cbbe12d 100644 (file)
@@ -151,7 +151,7 @@ static int wav_init_out (HWVoiceOut *hw, audsettings_t *as)
     le_store (hdr + 28, hw->info.freq << (bits16 + stereo), 4);
     le_store (hdr + 32, 1 << (bits16 + stereo), 2);
 
-    wav->f = fopen (conf.wav_path, "wb");
+    wav->f = qemu_fopen (conf.wav_path, "wb");
     if (!wav->f) {
         dolog ("Failed to open wave file `%s'\nReason: %s\n",
                conf.wav_path, strerror (errno));
@@ -185,7 +185,7 @@ static void wav_fini_out (HWVoiceOut *hw)
     qemu_fseek (wav->f, 32, SEEK_CUR);
     qemu_put_buffer (wav->f, dlen, 4);
 
-    fclose (wav->f);
+    qemu_fclose (wav->f);
     wav->f = NULL;
 
     qemu_free (wav->pcm_buf);
index 0f6f7bf01644e2273ac806983d2803ed82297142..d915fa02bf69a9845ccb8ab91c7aa2b723c05a08 100644 (file)
@@ -34,22 +34,19 @@ static void wav_destroy (void *opaque)
     uint32_t datalen = wav->bytes;
     uint32_t rifflen = datalen + 36;
 
-    if (!wav->f) {
-        return;
-    }
-
-    le_store (rlen, rifflen, 4);
-    le_store (dlen, datalen, 4);
-
-    qemu_fseek (wav->f, 4, SEEK_SET);
-    qemu_put_buffer (wav->f, rlen, 4);
-
-    qemu_fseek (wav->f, 32, SEEK_CUR);
-    qemu_put_buffer (wav->f, dlen, 4);
-    fclose (wav->f);
-    if (wav->path) {
-        qemu_free (wav->path);
+    if (wav->f) {
+        le_store (rlen, rifflen, 4);
+        le_store (dlen, datalen, 4);
+        
+        qemu_fseek (wav->f, 4, SEEK_SET);
+        qemu_put_buffer (wav->f, rlen, 4);
+        
+        qemu_fseek (wav->f, 32, SEEK_CUR);
+        qemu_put_buffer (wav->f, dlen, 4);
+        qemu_fclose (wav->f);
     }
+    
+    qemu_free (wav->path);
 }
 
 static void wav_capture (void *opaque, void *buf, int size)
@@ -135,7 +132,7 @@ int wav_start_capture (CaptureState *s, const char *path, int freq,
     le_store (hdr + 28, freq << shift, 4);
     le_store (hdr + 32, 1 << shift, 2);
 
-    wav->f = fopen (path, "wb");
+    wav->f = qemu_fopen (path, "wb");
     if (!wav->f) {
         term_printf ("Failed to open wave file `%s'\nReason: %s\n",
                      path, strerror (errno));
@@ -153,6 +150,8 @@ int wav_start_capture (CaptureState *s, const char *path, int freq,
     cap = AUD_add_capture (NULL, &as, &ops, wav);
     if (!cap) {
         term_printf ("Failed to add audio capture\n");
+        qemu_free (wav->path);
+        qemu_fclose (wav->f);
         qemu_free (wav);
         return -1;
     }
index 62317aff38a83ac6937de56baaa2155581151a09..35e2a6cf011235bbc416943b51d58253cb90e844 100644 (file)
@@ -28,7 +28,8 @@
 /**************************************************************/
 
 #define HEADER_MAGIC "Bochs Virtual HD Image"
-#define HEADER_VERSION 0x00010000
+#define HEADER_VERSION 0x00020000
+#define HEADER_V1 0x00010000
 #define HEADER_SIZE 512
 
 #define REDOLOG_TYPE "Redolog"
@@ -37,7 +38,7 @@
 // not allocated: 0xffffffff
 
 // always little-endian
-struct bochs_header {
+struct bochs_header_v1 {
     char magic[32]; // "Bochs Virtual HD Image"
     char type[16]; // "Redolog"
     char subtype[16]; // "Undoable" / "Volatile" / "Growing"
@@ -56,6 +57,27 @@ struct bochs_header {
     } extra;
 };
 
+// always little-endian
+struct bochs_header {
+    char magic[32]; // "Bochs Virtual HD Image"
+    char type[16]; // "Redolog"
+    char subtype[16]; // "Undoable" / "Volatile" / "Growing"
+    uint32_t version;
+    uint32_t header; // size of header
+    
+    union {
+       struct {
+           uint32_t catalog; // num of entries
+           uint32_t bitmap; // bitmap size
+           uint32_t extent; // extent size
+           uint32_t reserved; // for ???
+           uint64_t disk; // disk size
+           char padding[HEADER_SIZE - 64 - 8 - 24];
+       } redolog;
+       char padding[HEADER_SIZE - 64 - 8];
+    } extra;
+};
+
 typedef struct BDRVBochsState {
     int fd;
 
@@ -79,21 +101,23 @@ static int bochs_probe(const uint8_t *buf, int buf_size, const char *filename)
     if (!strcmp(bochs->magic, HEADER_MAGIC) &&
        !strcmp(bochs->type, REDOLOG_TYPE) &&
        !strcmp(bochs->subtype, GROWING_TYPE) &&
-       (le32_to_cpu(bochs->version) == HEADER_VERSION))
+       ((le32_to_cpu(bochs->version) == HEADER_VERSION) ||
+       (le32_to_cpu(bochs->version) == HEADER_V1)))
        return 100;
 
     return 0;
 }
 
-static int bochs_open(BlockDriverState *bs, const char *filename)
+static int bochs_open(BlockDriverState *bs, const char *filename, int flags)
 {
     BDRVBochsState *s = bs->opaque;
     int fd, i;
     struct bochs_header bochs;
+    struct bochs_header_v1 header_v1;
 
-    fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
+    fd = open(filename, O_RDWR | O_BINARY);
     if (fd < 0) {
-        fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
+        fd = open(filename, O_RDONLY | O_BINARY);
         if (fd < 0)
             return -1;
     }
@@ -109,11 +133,17 @@ static int bochs_open(BlockDriverState *bs, const char *filename)
     if (strcmp(bochs.magic, HEADER_MAGIC) ||
         strcmp(bochs.type, REDOLOG_TYPE) ||
         strcmp(bochs.subtype, GROWING_TYPE) ||
-       (le32_to_cpu(bochs.version) != HEADER_VERSION)) {
+       ((le32_to_cpu(bochs.version) != HEADER_VERSION) &&
+       (le32_to_cpu(bochs.version) != HEADER_V1))) {
         goto fail;
     }
 
-    bs->total_sectors = le64_to_cpu(bochs.extra.redolog.disk) / 512;
+    if (le32_to_cpu(bochs.version) == HEADER_V1) {
+      memcpy(&header_v1, &bochs, sizeof(bochs));
+      bs->total_sectors = le64_to_cpu(header_v1.extra.redolog.disk) / 512;
+    } else {
+      bs->total_sectors = le64_to_cpu(bochs.extra.redolog.disk) / 512;
+    }
 
     lseek(s->fd, le32_to_cpu(bochs.header), SEEK_SET);
 
index c617e1b64bc3d2b391515b1413d0edba5f040b36..f51c32d1bddbbbadf6bb4ad8d31c680c64e41352 100644 (file)
@@ -50,14 +50,14 @@ static int cloop_probe(const uint8_t *buf, int buf_size, const char *filename)
     return 0;
 }
 
-static int cloop_open(BlockDriverState *bs, const char *filename)
+static int cloop_open(BlockDriverState *bs, const char *filename, int flags)
 {
     BDRVCloopState *s = bs->opaque;
     uint32_t offsets_size,max_compressed_block_size=1,i;
 
-    s->fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
+    s->fd = open(filename, O_RDONLY | O_BINARY);
     if (s->fd < 0)
-        return -1;
+        return -errno;
     bs->read_only = 1;
 
     /* read header */
index 6af8b749759910eca057e6dd430ae01d8f099086..07c8a7bf167a704b835ad44ae2a82b37cc70da6d 100644 (file)
@@ -62,7 +62,7 @@ static int cow_probe(const uint8_t *buf, int buf_size, const char *filename)
         return 0;
 }
 
-static int cow_open(BlockDriverState *bs, const char *filename)
+static int cow_open(BlockDriverState *bs, const char *filename, int flags)
 {
     BDRVCowState *s = bs->opaque;
     int fd;
@@ -93,22 +93,6 @@ static int cow_open(BlockDriverState *bs, const char *filename)
     pstrcpy(bs->backing_file, sizeof(bs->backing_file), 
             cow_header.backing_file);
     
-#if 0
-    if (cow_header.backing_file[0] != '\0') {
-        if (stat(cow_header.backing_file, &st) != 0) {
-            fprintf(stderr, "%s: could not find original disk image '%s'\n", filename, cow_header.backing_file);
-            goto fail;
-        }
-        if (st.st_mtime != be32_to_cpu(cow_header.mtime)) {
-            fprintf(stderr, "%s: original raw disk image '%s' does not match saved timestamp\n", filename, cow_header.backing_file);
-            goto fail;
-            }
-        fd = open(cow_header.backing_file, O_RDONLY | O_LARGEFILE);
-        if (fd < 0)
-            goto fail;
-        bs->fd = fd;
-    }
-#endif
     /* mmap the bitmap */
     s->cow_bitmap_size = ((bs->total_sectors + 7) >> 3) + sizeof(cow_header);
     s->cow_bitmap_addr = mmap(get_mmap_addr(s->cow_bitmap_size), 
@@ -179,8 +163,15 @@ static int cow_read(BlockDriverState *bs, int64_t sector_num,
             if (ret != n * 512) 
                 return -1;
         } else {
+            if (bs->backing_hd) {
+                /* read from the base image */
+                ret = bdrv_read(bs->backing_hd, sector_num, buf, n);
+                if (ret < 0)
+                    return -1;
+            } else {
             memset(buf, 0, n * 512);
         }
+        }
         nb_sectors -= n;
         sector_num += n;
         buf += n * 512;
@@ -220,7 +211,7 @@ static int cow_create(const char *filename, int64_t image_sectors,
     if (flags)
         return -ENOTSUP;
 
-    cow_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE
+    cow_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 
               0644);
     if (cow_fd < 0)
         return -1;
@@ -228,18 +219,23 @@ static int cow_create(const char *filename, int64_t image_sectors,
     cow_header.magic = cpu_to_be32(COW_MAGIC);
     cow_header.version = cpu_to_be32(COW_VERSION);
     if (image_filename) {
+        /* Note: if no file, we put a dummy mtime */
+        cow_header.mtime = cpu_to_be32(0);
+
         fd = open(image_filename, O_RDONLY | O_BINARY);
         if (fd < 0) {
             close(cow_fd);
-            return -1;
+            goto mtime_fail;
         }
         if (fstat(fd, &st) != 0) {
             close(fd);
-            return -1;
+            goto mtime_fail;
         }
         close(fd);
         cow_header.mtime = cpu_to_be32(st.st_mtime);
-        realpath(image_filename, cow_header.backing_file);
+    mtime_fail:
+        pstrcpy(cow_header.backing_file, sizeof(cow_header.backing_file),
+                image_filename);
     }
     cow_header.sectorsize = cpu_to_be32(512);
     cow_header.size = cpu_to_be64(image_sectors * 512);
index a16ab926b59bd2c12aa492079d108befc5cbd680..a883a23f8e132155217ca6480ae8dea6707eeea1 100644 (file)
@@ -73,16 +73,16 @@ static off_t read_uint32(int fd)
        return be32_to_cpu(buffer);
 }
 
-static int dmg_open(BlockDriverState *bs, const char *filename)
+static int dmg_open(BlockDriverState *bs, const char *filename, int flags)
 {
     BDRVDMGState *s = bs->opaque;
     off_t info_begin,info_end,last_in_offset,last_out_offset;
     uint32_t count;
     uint32_t max_compressed_size=1,max_sectors_per_chunk=1,i;
 
-    s->fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
+    s->fd = open(filename, O_RDONLY | O_BINARY);
     if (s->fd < 0)
-        return -1;
+        return -errno;
     bs->read_only = 1;
     s->n_chunks = 0;
     s->offsets = s->lengths = s->sectors = s->sectorcounts = 0;
@@ -93,7 +93,7 @@ dmg_close:
        close(s->fd);
        /* open raw instead */
        bs->drv=&bdrv_raw;
-       return bs->drv->bdrv_open(bs,filename);
+       return bs->drv->bdrv_open(bs, filename, flags);
     }
     info_begin=read_off(s->fd);
     if(info_begin==0)
index e5b52fb86108aab79620f5b541d781628f15af61..d5333b379d7327b1bd414d2ed6ffcc652305a792 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Block driver for the QCOW format
  * 
- * Copyright (c) 2004 Fabrice Bellard
+ * Copyright (c) 2004-2006 Fabrice Bellard
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -53,7 +53,7 @@ typedef struct QCowHeader {
 #define L2_CACHE_SIZE 16
 
 typedef struct BDRVQcowState {
-    int fd;
+    BlockDriverState *hd;
     int cluster_bits;
     int cluster_size;
     int cluster_sectors;
@@ -89,20 +89,16 @@ static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename)
         return 0;
 }
 
-static int qcow_open(BlockDriverState *bs, const char *filename)
+static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
 {
     BDRVQcowState *s = bs->opaque;
-    int fd, len, i, shift;
+    int len, i, shift, ret;
     QCowHeader header;
-    
-    fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
-    if (fd < 0) {
-        fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
-        if (fd < 0)
-            return -1;
-    }
-    s->fd = fd;
-    if (read(fd, &header, sizeof(header)) != sizeof(header))
+
+    ret = bdrv_file_open(&s->hd, filename, flags);
+    if (ret < 0)
+        return ret;
+    if (bdrv_pread(s->hd, 0, &header, sizeof(header)) != sizeof(header))
         goto fail;
     be32_to_cpus(&header.magic);
     be32_to_cpus(&header.version);
@@ -138,8 +134,7 @@ static int qcow_open(BlockDriverState *bs, const char *filename)
     s->l1_table = qemu_malloc(s->l1_size * sizeof(uint64_t));
     if (!s->l1_table)
         goto fail;
-    lseek(fd, s->l1_table_offset, SEEK_SET);
-    if (read(fd, s->l1_table, s->l1_size * sizeof(uint64_t)) != 
+    if (bdrv_pread(s->hd, s->l1_table_offset, s->l1_table, s->l1_size * sizeof(uint64_t)) != 
         s->l1_size * sizeof(uint64_t))
         goto fail;
     for(i = 0;i < s->l1_size; i++) {
@@ -162,8 +157,7 @@ static int qcow_open(BlockDriverState *bs, const char *filename)
         len = header.backing_file_size;
         if (len > 1023)
             len = 1023;
-        lseek(fd, header.backing_file_offset, SEEK_SET);
-        if (read(fd, bs->backing_file, len) != len)
+        if (bdrv_pread(s->hd, header.backing_file_offset, bs->backing_file, len) != len)
             goto fail;
         bs->backing_file[len] = '\0';
     }
@@ -174,7 +168,7 @@ static int qcow_open(BlockDriverState *bs, const char *filename)
     qemu_free(s->l2_cache);
     qemu_free(s->cluster_cache);
     qemu_free(s->cluster_data);
-    close(fd);
+    bdrv_delete(s->hd);
     return -1;
 }
 
@@ -276,14 +270,14 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
         if (!allocate)
             return 0;
         /* allocate a new l2 entry */
-        l2_offset = lseek(s->fd, 0, SEEK_END);
+        l2_offset = bdrv_getlength(s->hd);
         /* round to cluster size */
         l2_offset = (l2_offset + s->cluster_size - 1) & ~(s->cluster_size - 1);
         /* update the L1 entry */
         s->l1_table[l1_index] = l2_offset;
         tmp = cpu_to_be64(l2_offset);
-        lseek(s->fd, s->l1_table_offset + l1_index * sizeof(tmp), SEEK_SET);
-        if (write(s->fd, &tmp, sizeof(tmp)) != sizeof(tmp))
+        if (bdrv_pwrite(s->hd, s->l1_table_offset + l1_index * sizeof(tmp), 
+                        &tmp, sizeof(tmp)) != sizeof(tmp))
             return 0;
         new_l2_table = 1;
     }
@@ -309,14 +303,13 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
         }
     }
     l2_table = s->l2_cache + (min_index << s->l2_bits);
-    lseek(s->fd, l2_offset, SEEK_SET);
     if (new_l2_table) {
         memset(l2_table, 0, s->l2_size * sizeof(uint64_t));
-        if (write(s->fd, l2_table, s->l2_size * sizeof(uint64_t)) !=
+        if (bdrv_pwrite(s->hd, l2_offset, l2_table, s->l2_size * sizeof(uint64_t)) !=
             s->l2_size * sizeof(uint64_t))
             return 0;
     } else {
-        if (read(s->fd, l2_table, s->l2_size * sizeof(uint64_t)) != 
+        if (bdrv_pread(s->hd, l2_offset, l2_table, s->l2_size * sizeof(uint64_t)) != 
             s->l2_size * sizeof(uint64_t))
             return 0;
     }
@@ -337,36 +330,35 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
                overwritten */
             if (decompress_cluster(s, cluster_offset) < 0)
                 return 0;
-            cluster_offset = lseek(s->fd, 0, SEEK_END);
+            cluster_offset = bdrv_getlength(s->hd);
             cluster_offset = (cluster_offset + s->cluster_size - 1) & 
                 ~(s->cluster_size - 1);
             /* write the cluster content */
-            lseek(s->fd, cluster_offset, SEEK_SET);
-            if (write(s->fd, s->cluster_cache, s->cluster_size) != 
+            if (bdrv_pwrite(s->hd, cluster_offset, s->cluster_cache, s->cluster_size) != 
                 s->cluster_size)
                 return -1;
         } else {
-            cluster_offset = lseek(s->fd, 0, SEEK_END);
+            cluster_offset = bdrv_getlength(s->hd);
             if (allocate == 1) {
                 /* round to cluster size */
                 cluster_offset = (cluster_offset + s->cluster_size - 1) & 
                     ~(s->cluster_size - 1);
-                ftruncate(s->fd, cluster_offset + s->cluster_size);
+                bdrv_truncate(s->hd, cluster_offset + s->cluster_size);
                 /* if encrypted, we must initialize the cluster
                    content which won't be written */
                 if (s->crypt_method && 
                     (n_end - n_start) < s->cluster_sectors) {
                     uint64_t start_sect;
                     start_sect = (offset & ~(s->cluster_size - 1)) >> 9;
-                    memset(s->cluster_data + 512, 0xaa, 512);
+                    memset(s->cluster_data + 512, 0x00, 512);
                     for(i = 0; i < s->cluster_sectors; i++) {
                         if (i < n_start || i >= n_end) {
                             encrypt_sectors(s, start_sect + i, 
                                             s->cluster_data, 
                                             s->cluster_data + 512, 1, 1,
                                             &s->aes_encrypt_key);
-                            lseek(s->fd, cluster_offset + i * 512, SEEK_SET);
-                            if (write(s->fd, s->cluster_data, 512) != 512)
+                            if (bdrv_pwrite(s->hd, cluster_offset + i * 512, 
+                                            s->cluster_data, 512) != 512)
                                 return -1;
                         }
                     }
@@ -379,8 +371,8 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
         /* update L2 table */
         tmp = cpu_to_be64(cluster_offset);
         l2_table[l2_index] = tmp;
-        lseek(s->fd, l2_offset + l2_index * sizeof(tmp), SEEK_SET);
-        if (write(s->fd, &tmp, sizeof(tmp)) != sizeof(tmp))
+        if (bdrv_pwrite(s->hd, 
+                        l2_offset + l2_index * sizeof(tmp), &tmp, sizeof(tmp)) != sizeof(tmp))
             return 0;
     }
     return cluster_offset;
@@ -438,8 +430,7 @@ static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset)
     if (s->cluster_cache_offset != coffset) {
         csize = cluster_offset >> (63 - s->cluster_bits);
         csize &= (s->cluster_size - 1);
-        lseek(s->fd, coffset, SEEK_SET);
-        ret = read(s->fd, s->cluster_data, csize);
+        ret = bdrv_pread(s->hd, coffset, s->cluster_data, csize);
         if (ret != csize) 
             return -1;
         if (decompress_buffer(s->cluster_cache, s->cluster_size,
@@ -451,6 +442,8 @@ static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset)
     return 0;
 }
 
+#if 0
+
 static int qcow_read(BlockDriverState *bs, int64_t sector_num, 
                      uint8_t *buf, int nb_sectors)
 {
@@ -465,14 +458,20 @@ static int qcow_read(BlockDriverState *bs, int64_t sector_num,
         if (n > nb_sectors)
             n = nb_sectors;
         if (!cluster_offset) {
-            memset(buf, 0, 512 * n);
+            if (bs->backing_hd) {
+                /* read from the base image */
+                ret = bdrv_read(bs->backing_hd, sector_num, buf, n);
+                if (ret < 0)
+                    return -1;
+            } else {
+                memset(buf, 0, 512 * n);
+            }
         } else if (cluster_offset & QCOW_OFLAG_COMPRESSED) {
             if (decompress_cluster(s, cluster_offset) < 0)
                 return -1;
             memcpy(buf, s->cluster_cache + index_in_cluster * 512, 512 * n);
         } else {
-            lseek(s->fd, cluster_offset + index_in_cluster * 512, SEEK_SET);
-            ret = read(s->fd, buf, n * 512);
+            ret = bdrv_pread(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512);
             if (ret != n * 512) 
                 return -1;
             if (s->crypt_method) {
@@ -486,6 +485,7 @@ static int qcow_read(BlockDriverState *bs, int64_t sector_num,
     }
     return 0;
 }
+#endif
 
 static int qcow_write(BlockDriverState *bs, int64_t sector_num, 
                      const uint8_t *buf, int nb_sectors)
@@ -504,13 +504,13 @@ static int qcow_write(BlockDriverState *bs, int64_t sector_num,
                                             index_in_cluster + n);
         if (!cluster_offset)
             return -1;
-        lseek(s->fd, cluster_offset + index_in_cluster * 512, SEEK_SET);
         if (s->crypt_method) {
             encrypt_sectors(s, sector_num, s->cluster_data, buf, n, 1,
                             &s->aes_encrypt_key);
-            ret = write(s->fd, s->cluster_data, n * 512);
+            ret = bdrv_pwrite(s->hd, cluster_offset + index_in_cluster * 512, 
+                              s->cluster_data, n * 512);
         } else {
-            ret = write(s->fd, buf, n * 512);
+            ret = bdrv_pwrite(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512);
         }
         if (ret != n * 512) 
             return -1;
@@ -522,6 +522,209 @@ static int qcow_write(BlockDriverState *bs, int64_t sector_num,
     return 0;
 }
 
+typedef struct QCowAIOCB {
+    BlockDriverAIOCB common;
+    int64_t sector_num;
+    uint8_t *buf;
+    int nb_sectors;
+    int n;
+    uint64_t cluster_offset;
+    uint8_t *cluster_data; 
+    BlockDriverAIOCB *hd_aiocb;
+} QCowAIOCB;
+
+static void qcow_aio_read_cb(void *opaque, int ret)
+{
+    QCowAIOCB *acb = opaque;
+    BlockDriverState *bs = acb->common.bs;
+    BDRVQcowState *s = bs->opaque;
+    int index_in_cluster;
+
+    acb->hd_aiocb = NULL;
+    if (ret < 0) {
+    fail:
+        acb->common.cb(acb->common.opaque, ret);
+        qemu_aio_release(acb);
+        return;
+    }
+
+ redo:
+    /* post process the read buffer */
+    if (!acb->cluster_offset) {
+        /* nothing to do */
+    } else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) {
+        /* nothing to do */
+    } else {
+        if (s->crypt_method) {
+            encrypt_sectors(s, acb->sector_num, acb->buf, acb->buf, 
+                            acb->n, 0, 
+                            &s->aes_decrypt_key);
+        }
+    }
+
+    acb->nb_sectors -= acb->n;
+    acb->sector_num += acb->n;
+    acb->buf += acb->n * 512;
+
+    if (acb->nb_sectors == 0) {
+        /* request completed */
+        acb->common.cb(acb->common.opaque, 0);
+        qemu_aio_release(acb);
+        return;
+    }
+    
+    /* prepare next AIO request */
+    acb->cluster_offset = get_cluster_offset(bs, acb->sector_num << 9, 
+                                             0, 0, 0, 0);
+    index_in_cluster = acb->sector_num & (s->cluster_sectors - 1);
+    acb->n = s->cluster_sectors - index_in_cluster;
+    if (acb->n > acb->nb_sectors)
+        acb->n = acb->nb_sectors;
+
+    if (!acb->cluster_offset) {
+        if (bs->backing_hd) {
+            /* read from the base image */
+            acb->hd_aiocb = bdrv_aio_read(bs->backing_hd,
+                acb->sector_num, acb->buf, acb->n, qcow_aio_read_cb, acb);
+            if (acb->hd_aiocb == NULL)
+                goto fail;
+        } else {
+            /* Note: in this case, no need to wait */
+            memset(acb->buf, 0, 512 * acb->n);
+            goto redo;
+        }
+    } else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) {
+        /* add AIO support for compressed blocks ? */
+        if (decompress_cluster(s, acb->cluster_offset) < 0)
+            goto fail;
+        memcpy(acb->buf, 
+               s->cluster_cache + index_in_cluster * 512, 512 * acb->n);
+        goto redo;
+    } else {
+        if ((acb->cluster_offset & 511) != 0) {
+            ret = -EIO;
+            goto fail;
+        }
+        acb->hd_aiocb = bdrv_aio_read(s->hd,
+                            (acb->cluster_offset >> 9) + index_in_cluster, 
+                            acb->buf, acb->n, qcow_aio_read_cb, acb);
+        if (acb->hd_aiocb == NULL)
+            goto fail;
+    }
+}
+
+static BlockDriverAIOCB *qcow_aio_read(BlockDriverState *bs,
+        int64_t sector_num, uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque)
+{
+    QCowAIOCB *acb;
+
+    acb = qemu_aio_get(bs, cb, opaque);
+    if (!acb)
+        return NULL;
+    acb->hd_aiocb = NULL;
+    acb->sector_num = sector_num;
+    acb->buf = buf;
+    acb->nb_sectors = nb_sectors;
+    acb->n = 0;
+    acb->cluster_offset = 0;    
+
+    qcow_aio_read_cb(acb, 0);
+    return &acb->common;
+}
+
+static void qcow_aio_write_cb(void *opaque, int ret)
+{
+    QCowAIOCB *acb = opaque;
+    BlockDriverState *bs = acb->common.bs;
+    BDRVQcowState *s = bs->opaque;
+    int index_in_cluster;
+    uint64_t cluster_offset;
+    const uint8_t *src_buf;
+
+    acb->hd_aiocb = NULL;
+
+    if (ret < 0) {
+    fail:
+        acb->common.cb(acb->common.opaque, ret);
+        qemu_aio_release(acb);
+        return;
+    }
+
+    acb->nb_sectors -= acb->n;
+    acb->sector_num += acb->n;
+    acb->buf += acb->n * 512;
+
+    if (acb->nb_sectors == 0) {
+        /* request completed */
+        acb->common.cb(acb->common.opaque, 0);
+        qemu_aio_release(acb);
+        return;
+    }
+    
+    index_in_cluster = acb->sector_num & (s->cluster_sectors - 1);
+    acb->n = s->cluster_sectors - index_in_cluster;
+    if (acb->n > acb->nb_sectors)
+        acb->n = acb->nb_sectors;
+    cluster_offset = get_cluster_offset(bs, acb->sector_num << 9, 1, 0, 
+                                        index_in_cluster, 
+                                        index_in_cluster + acb->n);
+    if (!cluster_offset || (cluster_offset & 511) != 0) {
+        ret = -EIO;
+        goto fail;
+    }
+    if (s->crypt_method) {
+        if (!acb->cluster_data) {
+            acb->cluster_data = qemu_mallocz(s->cluster_size);
+            if (!acb->cluster_data) {
+                ret = -ENOMEM;
+                goto fail;
+            }
+        }
+        encrypt_sectors(s, acb->sector_num, acb->cluster_data, acb->buf, 
+                        acb->n, 1, &s->aes_encrypt_key);
+        src_buf = acb->cluster_data;
+    } else {
+        src_buf = acb->buf;
+    }
+    acb->hd_aiocb = bdrv_aio_write(s->hd,
+                                   (cluster_offset >> 9) + index_in_cluster, 
+                                   src_buf, acb->n, 
+                                   qcow_aio_write_cb, acb);
+    if (acb->hd_aiocb == NULL)
+        goto fail;
+}
+
+static BlockDriverAIOCB *qcow_aio_write(BlockDriverState *bs,
+        int64_t sector_num, const uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque)
+{
+    BDRVQcowState *s = bs->opaque;
+    QCowAIOCB *acb;
+    
+    s->cluster_cache_offset = -1; /* disable compressed cache */
+
+    acb = qemu_aio_get(bs, cb, opaque);
+    if (!acb)
+        return NULL;
+    acb->hd_aiocb = NULL;
+    acb->sector_num = sector_num;
+    acb->buf = (uint8_t *)buf;
+    acb->nb_sectors = nb_sectors;
+    acb->n = 0;
+    
+    qcow_aio_write_cb(acb, 0);
+    return &acb->common;
+}
+
+static void qcow_aio_cancel(BlockDriverAIOCB *blockacb)
+{
+    QCowAIOCB *acb = (QCowAIOCB *)blockacb;
+    if (acb->hd_aiocb)
+        bdrv_aio_cancel(acb->hd_aiocb);
+    qemu_aio_release(acb);
+}
+
 static void qcow_close(BlockDriverState *bs)
 {
     BDRVQcowState *s = bs->opaque;
@@ -529,7 +732,7 @@ static void qcow_close(BlockDriverState *bs)
     qemu_free(s->l2_cache);
     qemu_free(s->cluster_cache);
     qemu_free(s->cluster_data);
-    close(s->fd);
+    bdrv_delete(s->hd);
 }
 
 static int qcow_create(const char *filename, int64_t total_size,
@@ -537,12 +740,9 @@ static int qcow_create(const char *filename, int64_t total_size,
 {
     int fd, header_size, backing_filename_len, l1_size, i, shift;
     QCowHeader header;
-    char backing_filename[1024];
     uint64_t tmp;
-    struct stat st;
 
-    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, 
-              0644);
+    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
     if (fd < 0)
         return -1;
     memset(&header, 0, sizeof(header));
@@ -552,28 +752,11 @@ static int qcow_create(const char *filename, int64_t total_size,
     header_size = sizeof(header);
     backing_filename_len = 0;
     if (backing_file) {
-       if (strcmp(backing_file, "fat:")) {
-           const char *p;
-           /* XXX: this is a hack: we do not attempt to check for URL
-              like syntax */
-           p = strchr(backing_file, ':');
-           if (p && (p - backing_file) >= 2) {
-               /* URL like but exclude "c:" like filenames */
-               pstrcpy(backing_filename, sizeof(backing_filename),
-                       backing_file);
-           } else {
-               realpath(backing_file, backing_filename);
-               if (stat(backing_filename, &st) != 0) {
-                   return -1;
-               }
-           }
-           header.backing_file_offset = cpu_to_be64(header_size);
-           backing_filename_len = strlen(backing_filename);
-           header.backing_file_size = cpu_to_be32(backing_filename_len);
-           header_size += backing_filename_len;
-       } else
-           backing_file = NULL;
-        header.mtime = cpu_to_be32(st.st_mtime);
+        header.backing_file_offset = cpu_to_be64(header_size);
+        backing_filename_len = strlen(backing_file);
+        header.backing_file_size = cpu_to_be32(backing_filename_len);
+        header_size += backing_filename_len;
+        header.mtime = cpu_to_be32(0);
         header.cluster_bits = 9; /* 512 byte cluster to avoid copying
                                     unmodifyed sectors */
         header.l2_bits = 12; /* 32 KB L2 tables */
@@ -595,7 +778,7 @@ static int qcow_create(const char *filename, int64_t total_size,
     /* write all the data */
     write(fd, &header, sizeof(header));
     if (backing_file) {
-        write(fd, backing_filename, backing_filename_len);
+        write(fd, backing_file, backing_filename_len);
     }
     lseek(fd, header_size, SEEK_SET);
     tmp = 0;
@@ -606,16 +789,18 @@ static int qcow_create(const char *filename, int64_t total_size,
     return 0;
 }
 
-int qcow_make_empty(BlockDriverState *bs)
+static int qcow_make_empty(BlockDriverState *bs)
 {
     BDRVQcowState *s = bs->opaque;
     uint32_t l1_length = s->l1_size * sizeof(uint64_t);
+    int ret;
 
     memset(s->l1_table, 0, l1_length);
-    lseek(s->fd, s->l1_table_offset, SEEK_SET);
-    if (write(s->fd, s->l1_table, l1_length) < 0)
+    if (bdrv_pwrite(s->hd, s->l1_table_offset, s->l1_table, l1_length) < 0)
        return -1;
-    ftruncate(s->fd, s->l1_table_offset + l1_length);
+    ret = bdrv_truncate(s->hd, s->l1_table_offset + l1_length);
+    if (ret < 0)
+        return ret;
 
     memset(s->l2_cache, 0, s->l2_size * L2_CACHE_SIZE * sizeof(uint64_t));
     memset(s->l2_cache_offsets, 0, L2_CACHE_SIZE * sizeof(uint64_t));
@@ -624,18 +809,10 @@ int qcow_make_empty(BlockDriverState *bs)
     return 0;
 }
 
-int qcow_get_cluster_size(BlockDriverState *bs)
-{
-    BDRVQcowState *s = bs->opaque;
-    if (bs->drv != &bdrv_qcow)
-        return -1;
-    return s->cluster_size;
-}
-
 /* XXX: put compressed sectors first, then all the cluster aligned
    tables to avoid losing bytes in alignment */
-int qcow_compress_cluster(BlockDriverState *bs, int64_t sector_num, 
-                          const uint8_t *buf)
+static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num, 
+                                 const uint8_t *buf, int nb_sectors)
 {
     BDRVQcowState *s = bs->opaque;
     z_stream strm;
@@ -643,8 +820,8 @@ int qcow_compress_cluster(BlockDriverState *bs, int64_t sector_num,
     uint8_t *out_buf;
     uint64_t cluster_offset;
 
-    if (bs->drv != &bdrv_qcow)
-        return -1;
+    if (nb_sectors != s->cluster_sectors)
+        return -EINVAL;
 
     out_buf = qemu_malloc(s->cluster_size + (s->cluster_size / 1000) + 128);
     if (!out_buf)
@@ -682,8 +859,7 @@ int qcow_compress_cluster(BlockDriverState *bs, int64_t sector_num,
         cluster_offset = get_cluster_offset(bs, sector_num << 9, 2, 
                                             out_len, 0, 0);
         cluster_offset &= s->cluster_offset_mask;
-        lseek(s->fd, cluster_offset, SEEK_SET);
-        if (write(s->fd, out_buf, out_len) != out_len) {
+        if (bdrv_pwrite(s->hd, cluster_offset, out_buf, out_len) != out_len) {
             qemu_free(out_buf);
             return -1;
         }
@@ -696,7 +872,14 @@ int qcow_compress_cluster(BlockDriverState *bs, int64_t sector_num,
 static void qcow_flush(BlockDriverState *bs)
 {
     BDRVQcowState *s = bs->opaque;
-    fsync(s->fd);
+    bdrv_flush(s->hd);
+}
+
+static int qcow_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
+{
+    BDRVQcowState *s = bs->opaque;
+    bdi->cluster_size = s->cluster_size;
+    return 0;
 }
 
 BlockDriver bdrv_qcow = {
@@ -704,14 +887,19 @@ BlockDriver bdrv_qcow = {
     sizeof(BDRVQcowState),
     qcow_probe,
     qcow_open,
-    qcow_read,
-    qcow_write,
+    NULL,
+    NULL,
     qcow_close,
     qcow_create,
     qcow_flush,
     qcow_is_allocated,
     qcow_set_key,
-    qcow_make_empty
+    qcow_make_empty,
+
+    .bdrv_aio_read = qcow_aio_read,
+    .bdrv_aio_write = qcow_aio_write,
+    .bdrv_aio_cancel = qcow_aio_cancel,
+    .aiocb_size = sizeof(QCowAIOCB),
+    .bdrv_write_compressed = qcow_write_compressed,
+    .bdrv_get_info = qcow_get_info,
 };
-
-
diff --git a/tools/ioemu/block-qcow2.c b/tools/ioemu/block-qcow2.c
new file mode 100644 (file)
index 0000000..a876ea2
--- /dev/null
@@ -0,0 +1,2246 @@
+/*
+ * Block driver for the QCOW version 2 format
+ * 
+ * Copyright (c) 2004-2006 Fabrice Bellard
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+#include "block_int.h"
+#include <zlib.h>
+#include "aes.h"
+#include <assert.h>
+
+/*
+  Differences with QCOW:
+
+  - Support for multiple incremental snapshots.
+  - Memory management by reference counts.
+  - Clusters which have a reference count of one have the bit
+    QCOW_OFLAG_COPIED to optimize write performance.
+  - Size of compressed clusters is stored in sectors to reduce bit usage 
+    in the cluster offsets.
+  - Support for storing additional data (such as the VM state) in the
+    snapshots.  
+  - If a backing store is used, the cluster size is not constrained
+    (could be backported to QCOW).
+  - L2 tables have always a size of one cluster.
+*/
+
+//#define DEBUG_ALLOC
+//#define DEBUG_ALLOC2
+#define QCOW_MAGIC (('Q' << 24) | ('F' << 16) | ('I' << 8) | 0xfb)
+#define QCOW_VERSION 2
+
+#define QCOW_CRYPT_NONE 0
+#define QCOW_CRYPT_AES  1
+
+/* indicate that the refcount of the referenced cluster is exactly one. */
+#define QCOW_OFLAG_COPIED     (1LL << 63)
+/* indicate that the cluster is compressed (they never have the copied flag) */
+#define QCOW_OFLAG_COMPRESSED (1LL << 62)
+
+#define REFCOUNT_SHIFT 1 /* refcount size is 2 bytes */
+
+#ifndef offsetof
+#define offsetof(type, field) ((size_t) &((type *)0)->field)
+#endif
+
+typedef struct QCowHeader {
+    uint32_t magic;
+    uint32_t version;
+    uint64_t backing_file_offset;
+    uint32_t backing_file_size;
+    uint32_t cluster_bits;
+    uint64_t size; /* in bytes */
+    uint32_t crypt_method;
+    uint32_t l1_size; /* XXX: save number of clusters instead ? */
+    uint64_t l1_table_offset;
+    uint64_t refcount_table_offset;
+    uint32_t refcount_table_clusters;
+    uint32_t nb_snapshots;
+    uint64_t snapshots_offset;
+} QCowHeader;
+
+typedef struct __attribute__((packed)) QCowSnapshotHeader {
+    /* header is 8 byte aligned */
+    uint64_t l1_table_offset;
+
+    uint32_t l1_size;
+    uint16_t id_str_size;
+    uint16_t name_size;
+
+    uint32_t date_sec;
+    uint32_t date_nsec;
+
+    uint64_t vm_clock_nsec;
+
+    uint32_t vm_state_size;
+    uint32_t extra_data_size; /* for extension */
+    /* extra data follows */
+    /* id_str follows */
+    /* name follows  */
+} QCowSnapshotHeader;
+
+#define L2_CACHE_SIZE 16
+
+typedef struct QCowSnapshot {
+    uint64_t l1_table_offset;
+    uint32_t l1_size;
+    char *id_str;
+    char *name;
+    uint32_t vm_state_size;
+    uint32_t date_sec;
+    uint32_t date_nsec;
+    uint64_t vm_clock_nsec;
+} QCowSnapshot;
+
+typedef struct BDRVQcowState {
+    BlockDriverState *hd;
+    int cluster_bits;
+    int cluster_size;
+    int cluster_sectors;
+    int l2_bits;
+    int l2_size;
+    int l1_size;
+    int l1_vm_state_index;
+    int csize_shift;
+    int csize_mask;
+    uint64_t cluster_offset_mask;
+    uint64_t l1_table_offset;
+    uint64_t *l1_table;
+    uint64_t *l2_cache;
+    uint64_t l2_cache_offsets[L2_CACHE_SIZE];
+    uint32_t l2_cache_counts[L2_CACHE_SIZE];
+    uint8_t *cluster_cache;
+    uint8_t *cluster_data;
+    uint64_t cluster_cache_offset;
+
+    uint64_t *refcount_table;
+    uint64_t refcount_table_offset;
+    uint32_t refcount_table_size;
+    uint64_t refcount_block_cache_offset;
+    uint16_t *refcount_block_cache;
+    int64_t free_cluster_index;
+    int64_t free_byte_offset;
+
+    uint32_t crypt_method; /* current crypt method, 0 if no key yet */
+    uint32_t crypt_method_header;
+    AES_KEY aes_encrypt_key;
+    AES_KEY aes_decrypt_key;
+    uint64_t snapshots_offset;
+    int snapshots_size;
+    int nb_snapshots;
+    QCowSnapshot *snapshots;
+} BDRVQcowState;
+
+static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset);
+static int qcow_read(BlockDriverState *bs, int64_t sector_num, 
+                     uint8_t *buf, int nb_sectors);
+static int qcow_read_snapshots(BlockDriverState *bs);
+static void qcow_free_snapshots(BlockDriverState *bs);
+static int refcount_init(BlockDriverState *bs);
+static void refcount_close(BlockDriverState *bs);
+static int get_refcount(BlockDriverState *bs, int64_t cluster_index);
+static int update_cluster_refcount(BlockDriverState *bs, 
+                                   int64_t cluster_index,
+                                   int addend);
+static void update_refcount(BlockDriverState *bs, 
+                            int64_t offset, int64_t length, 
+                            int addend);
+static int64_t alloc_clusters(BlockDriverState *bs, int64_t size);
+static int64_t alloc_bytes(BlockDriverState *bs, int size);
+static void free_clusters(BlockDriverState *bs, 
+                          int64_t offset, int64_t size);
+#ifdef DEBUG_ALLOC
+static void check_refcounts(BlockDriverState *bs);
+#endif
+
+static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename)
+{
+    const QCowHeader *cow_header = (const void *)buf;
+    
+    if (buf_size >= sizeof(QCowHeader) &&
+        be32_to_cpu(cow_header->magic) == QCOW_MAGIC &&
+        be32_to_cpu(cow_header->version) == QCOW_VERSION) 
+        return 100;
+    else
+        return 0;
+}
+
+static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
+{
+    BDRVQcowState *s = bs->opaque;
+    int len, i, shift, ret;
+    QCowHeader header;
+
+    ret = bdrv_file_open(&s->hd, filename, flags);
+    if (ret < 0)
+        return ret;
+    if (bdrv_pread(s->hd, 0, &header, sizeof(header)) != sizeof(header))
+        goto fail;
+    be32_to_cpus(&header.magic);
+    be32_to_cpus(&header.version);
+    be64_to_cpus(&header.backing_file_offset);
+    be32_to_cpus(&header.backing_file_size);
+    be64_to_cpus(&header.size);
+    be32_to_cpus(&header.cluster_bits);
+    be32_to_cpus(&header.crypt_method);
+    be64_to_cpus(&header.l1_table_offset);
+    be32_to_cpus(&header.l1_size);
+    be64_to_cpus(&header.refcount_table_offset);
+    be32_to_cpus(&header.refcount_table_clusters);
+    be64_to_cpus(&header.snapshots_offset);
+    be32_to_cpus(&header.nb_snapshots);
+    
+    if (header.magic != QCOW_MAGIC || header.version != QCOW_VERSION)
+        goto fail;
+    if (header.size <= 1 || 
+        header.cluster_bits < 9 || 
+        header.cluster_bits > 16)
+        goto fail;
+    if (header.crypt_method > QCOW_CRYPT_AES)
+        goto fail;
+    s->crypt_method_header = header.crypt_method;
+    if (s->crypt_method_header)
+        bs->encrypted = 1;
+    s->cluster_bits = header.cluster_bits;
+    s->cluster_size = 1 << s->cluster_bits;
+    s->cluster_sectors = 1 << (s->cluster_bits - 9);
+    s->l2_bits = s->cluster_bits - 3; /* L2 is always one cluster */
+    s->l2_size = 1 << s->l2_bits;
+    bs->total_sectors = header.size / 512;
+    s->csize_shift = (62 - (s->cluster_bits - 8));
+    s->csize_mask = (1 << (s->cluster_bits - 8)) - 1;
+    s->cluster_offset_mask = (1LL << s->csize_shift) - 1;
+    s->refcount_table_offset = header.refcount_table_offset;
+    s->refcount_table_size = 
+        header.refcount_table_clusters << (s->cluster_bits - 3);
+
+    s->snapshots_offset = header.snapshots_offset;
+    s->nb_snapshots = header.nb_snapshots;
+
+    /* read the level 1 table */
+    s->l1_size = header.l1_size;
+    shift = s->cluster_bits + s->l2_bits;
+    s->l1_vm_state_index = (header.size + (1LL << shift) - 1) >> shift;
+    /* the L1 table must contain at least enough entries to put
+       header.size bytes */
+    if (s->l1_size < s->l1_vm_state_index)
+        goto fail;
+    s->l1_table_offset = header.l1_table_offset;
+    s->l1_table = qemu_malloc(s->l1_size * sizeof(uint64_t));
+    if (!s->l1_table)
+        goto fail;
+    if (bdrv_pread(s->hd, s->l1_table_offset, s->l1_table, s->l1_size * sizeof(uint64_t)) != 
+        s->l1_size * sizeof(uint64_t))
+        goto fail;
+    for(i = 0;i < s->l1_size; i++) {
+        be64_to_cpus(&s->l1_table[i]);
+    }
+    /* alloc L2 cache */
+    s->l2_cache = qemu_malloc(s->l2_size * L2_CACHE_SIZE * sizeof(uint64_t));
+    if (!s->l2_cache)
+        goto fail;
+    s->cluster_cache = qemu_malloc(s->cluster_size);
+    if (!s->cluster_cache)
+        goto fail;
+    /* one more sector for decompressed data alignment */
+    s->cluster_data = qemu_malloc(s->cluster_size + 512);
+    if (!s->cluster_data)
+        goto fail;
+    s->cluster_cache_offset = -1;
+    
+    if (refcount_init(bs) < 0)
+        goto fail;
+
+    /* read the backing file name */
+    if (header.backing_file_offset != 0) {
+        len = header.backing_file_size;
+        if (len > 1023)
+            len = 1023;
+        if (bdrv_pread(s->hd, header.backing_file_offset, bs->backing_file, len) != len)
+            goto fail;
+        bs->backing_file[len] = '\0';
+    }
+    if (qcow_read_snapshots(bs) < 0)
+        goto fail;
+
+#ifdef DEBUG_ALLOC
+    check_refcounts(bs);
+#endif
+    return 0;
+
+ fail:
+    qcow_free_snapshots(bs);
+    refcount_close(bs);
+    qemu_free(s->l1_table);
+    qemu_free(s->l2_cache);
+    qemu_free(s->cluster_cache);
+    qemu_free(s->cluster_data);
+    bdrv_delete(s->hd);
+    return -1;
+}
+
+static int qcow_set_key(BlockDriverState *bs, const char *key)
+{
+    BDRVQcowState *s = bs->opaque;
+    uint8_t keybuf[16];
+    int len, i;
+    
+    memset(keybuf, 0, 16);
+    len = strlen(key);
+    if (len > 16)
+        len = 16;
+    /* XXX: we could compress the chars to 7 bits to increase
+       entropy */
+    for(i = 0;i < len;i++) {
+        keybuf[i] = key[i];
+    }
+    s->crypt_method = s->crypt_method_header;
+
+    if (AES_set_encrypt_key(keybuf, 128, &s->aes_encrypt_key) != 0)
+        return -1;
+    if (AES_set_decrypt_key(keybuf, 128, &s->aes_decrypt_key) != 0)
+        return -1;
+#if 0
+    /* test */
+    {
+        uint8_t in[16];
+        uint8_t out[16];
+        uint8_t tmp[16];
+        for(i=0;i<16;i++)
+            in[i] = i;
+        AES_encrypt(in, tmp, &s->aes_encrypt_key);
+        AES_decrypt(tmp, out, &s->aes_decrypt_key);
+        for(i = 0; i < 16; i++)
+            printf(" %02x", tmp[i]);
+        printf("\n");
+        for(i = 0; i < 16; i++)
+            printf(" %02x", out[i]);
+        printf("\n");
+    }
+#endif
+    return 0;
+}
+
+/* The crypt function is compatible with the linux cryptoloop
+   algorithm for < 4 GB images. NOTE: out_buf == in_buf is
+   supported */
+static void encrypt_sectors(BDRVQcowState *s, int64_t sector_num,
+                            uint8_t *out_buf, const uint8_t *in_buf,
+                            int nb_sectors, int enc,
+                            const AES_KEY *key)
+{
+    union {
+        uint64_t ll[2];
+        uint8_t b[16];
+    } ivec;
+    int i;
+
+    for(i = 0; i < nb_sectors; i++) {
+        ivec.ll[0] = cpu_to_le64(sector_num);
+        ivec.ll[1] = 0;
+        AES_cbc_encrypt(in_buf, out_buf, 512, key, 
+                        ivec.b, enc);
+        sector_num++;
+        in_buf += 512;
+        out_buf += 512;
+    }
+}
+
+static int copy_sectors(BlockDriverState *bs, uint64_t start_sect,
+                        uint64_t cluster_offset, int n_start, int n_end)
+{
+    BDRVQcowState *s = bs->opaque;
+    int n, ret;
+
+    n = n_end - n_start;
+    if (n <= 0)
+        return 0;
+    ret = qcow_read(bs, start_sect + n_start, s->cluster_data, n);
+    if (ret < 0)
+        return ret;
+    if (s->crypt_method) {
+        encrypt_sectors(s, start_sect + n_start, 
+                        s->cluster_data, 
+                        s->cluster_data, n, 1,
+                        &s->aes_encrypt_key);
+    }
+    ret = bdrv_write(s->hd, (cluster_offset >> 9) + n_start, 
+                     s->cluster_data, n);
+    if (ret < 0)
+        return ret;
+    return 0;
+}
+
+static void l2_cache_reset(BlockDriverState *bs)
+{
+    BDRVQcowState *s = bs->opaque;
+
+    memset(s->l2_cache, 0, s->l2_size * L2_CACHE_SIZE * sizeof(uint64_t));
+    memset(s->l2_cache_offsets, 0, L2_CACHE_SIZE * sizeof(uint64_t));
+    memset(s->l2_cache_counts, 0, L2_CACHE_SIZE * sizeof(uint32_t));
+}
+
+static inline int l2_cache_new_entry(BlockDriverState *bs)
+{
+    BDRVQcowState *s = bs->opaque;
+    uint32_t min_count;
+    int min_index, i;
+
+    /* find a new entry in the least used one */
+    min_index = 0;
+    min_count = 0xffffffff;
+    for(i = 0; i < L2_CACHE_SIZE; i++) {
+        if (s->l2_cache_counts[i] < min_count) {
+            min_count = s->l2_cache_counts[i];
+            min_index = i;
+        }
+    }
+    return min_index;
+}
+
+static int64_t align_offset(int64_t offset, int n)
+{
+    offset = (offset + n - 1) & ~(n - 1);
+    return offset;
+}
+
+static int grow_l1_table(BlockDriverState *bs, int min_size)
+{
+    BDRVQcowState *s = bs->opaque;
+    int new_l1_size, new_l1_size2, ret, i;
+    uint64_t *new_l1_table;
+    uint64_t new_l1_table_offset;
+    uint64_t data64;
+    uint32_t data32;
+
+    new_l1_size = s->l1_size;
+    if (min_size <= new_l1_size)
+        return 0;
+    while (min_size > new_l1_size) {
+        new_l1_size = (new_l1_size * 3 + 1) / 2;
+    }
+#ifdef DEBUG_ALLOC2
+    printf("grow l1_table from %d to %d\n", s->l1_size, new_l1_size);
+#endif
+
+    new_l1_size2 = sizeof(uint64_t) * new_l1_size;
+    new_l1_table = qemu_mallocz(new_l1_size2);
+    if (!new_l1_table)
+        return -ENOMEM;
+    memcpy(new_l1_table, s->l1_table, s->l1_size * sizeof(uint64_t));
+
+    /* write new table (align to cluster) */
+    new_l1_table_offset = alloc_clusters(bs, new_l1_size2);
+    
+    for(i = 0; i < s->l1_size; i++)
+        new_l1_table[i] = cpu_to_be64(new_l1_table[i]);
+    ret = bdrv_pwrite(s->hd, new_l1_table_offset, new_l1_table, new_l1_size2);
+    if (ret != new_l1_size2)
+        goto fail;
+    for(i = 0; i < s->l1_size; i++)
+        new_l1_table[i] = be64_to_cpu(new_l1_table[i]);
+    
+    /* set new table */
+    data64 = cpu_to_be64(new_l1_table_offset);
+    if (bdrv_pwrite(s->hd, offsetof(QCowHeader, l1_table_offset),
+                    &data64, sizeof(data64)) != sizeof(data64))
+        goto fail;
+    data32 = cpu_to_be32(new_l1_size);
+    if (bdrv_pwrite(s->hd, offsetof(QCowHeader, l1_size),
+                    &data32, sizeof(data32)) != sizeof(data32))
+        goto fail;
+    qemu_free(s->l1_table);
+    free_clusters(bs, s->l1_table_offset, s->l1_size * sizeof(uint64_t));
+    s->l1_table_offset = new_l1_table_offset;
+    s->l1_table = new_l1_table;
+    s->l1_size = new_l1_size;
+    return 0;
+ fail:
+    qemu_free(s->l1_table);
+    return -EIO;
+}
+
+/* 'allocate' is:
+ *
+ * 0 not to allocate.
+ *
+ * 1 to allocate a normal cluster (for sector indexes 'n_start' to
+ * 'n_end')
+ *
+ * 2 to allocate a compressed cluster of size
+ * 'compressed_size'. 'compressed_size' must be > 0 and <
+ * cluster_size 
+ *
+ * return 0 if not allocated.
+ */
+static uint64_t get_cluster_offset(BlockDriverState *bs,
+                                   uint64_t offset, int allocate,
+                                   int compressed_size,
+                                   int n_start, int n_end)
+{
+    BDRVQcowState *s = bs->opaque;
+    int min_index, i, j, l1_index, l2_index, ret;
+    uint64_t l2_offset, *l2_table, cluster_offset, tmp, old_l2_offset;
+    
+    l1_index = offset >> (s->l2_bits + s->cluster_bits);
+    if (l1_index >= s->l1_size) {
+        /* outside l1 table is allowed: we grow the table if needed */
+        if (!allocate)
+            return 0;
+        if (grow_l1_table(bs, l1_index + 1) < 0)
+            return 0;
+    }
+    l2_offset = s->l1_table[l1_index];
+    if (!l2_offset) {
+        if (!allocate)
+            return 0;
+    l2_allocate:
+        old_l2_offset = l2_offset;
+        /* allocate a new l2 entry */
+        l2_offset = alloc_clusters(bs, s->l2_size * sizeof(uint64_t));
+        /* update the L1 entry */
+        s->l1_table[l1_index] = l2_offset | QCOW_OFLAG_COPIED;
+        tmp = cpu_to_be64(l2_offset | QCOW_OFLAG_COPIED);
+        if (bdrv_pwrite(s->hd, s->l1_table_offset + l1_index * sizeof(tmp), 
+                        &tmp, sizeof(tmp)) != sizeof(tmp))
+            return 0;
+        min_index = l2_cache_new_entry(bs);
+        l2_table = s->l2_cache + (min_index << s->l2_bits);
+
+        if (old_l2_offset == 0) {
+            memset(l2_table, 0, s->l2_size * sizeof(uint64_t));
+        } else {
+            if (bdrv_pread(s->hd, old_l2_offset, 
+                           l2_table, s->l2_size * sizeof(uint64_t)) !=
+                s->l2_size * sizeof(uint64_t))
+                return 0;
+        }
+        if (bdrv_pwrite(s->hd, l2_offset, 
+                        l2_table, s->l2_size * sizeof(uint64_t)) !=
+            s->l2_size * sizeof(uint64_t))
+            return 0;
+    } else {
+        if (!(l2_offset & QCOW_OFLAG_COPIED)) {
+            if (allocate) {
+                free_clusters(bs, l2_offset, s->l2_size * sizeof(uint64_t));
+                goto l2_allocate;
+            }
+        } else {
+            l2_offset &= ~QCOW_OFLAG_COPIED;
+        }
+        for(i = 0; i < L2_CACHE_SIZE; i++) {
+            if (l2_offset == s->l2_cache_offsets[i]) {
+                /* increment the hit count */
+                if (++s->l2_cache_counts[i] == 0xffffffff) {
+                    for(j = 0; j < L2_CACHE_SIZE; j++) {
+                        s->l2_cache_counts[j] >>= 1;
+                    }
+                }
+                l2_table = s->l2_cache + (i << s->l2_bits);
+                goto found;
+            }
+        }
+        /* not found: load a new entry in the least used one */
+        min_index = l2_cache_new_entry(bs);
+        l2_table = s->l2_cache + (min_index << s->l2_bits);
+        if (bdrv_pread(s->hd, l2_offset, l2_table, s->l2_size * sizeof(uint64_t)) != 
+            s->l2_size * sizeof(uint64_t))
+            return 0;
+    }
+    s->l2_cache_offsets[min_index] = l2_offset;
+    s->l2_cache_counts[min_index] = 1;
+ found:
+    l2_index = (offset >> s->cluster_bits) & (s->l2_size - 1);
+    cluster_offset = be64_to_cpu(l2_table[l2_index]);
+    if (!cluster_offset) {
+        if (!allocate)
+            return cluster_offset;
+    } else if (!(cluster_offset & QCOW_OFLAG_COPIED)) {
+        if (!allocate)
+            return cluster_offset;
+        /* free the cluster */
+        if (cluster_offset & QCOW_OFLAG_COMPRESSED) {
+            int nb_csectors;
+            nb_csectors = ((cluster_offset >> s->csize_shift) & 
+                           s->csize_mask) + 1;
+            free_clusters(bs, (cluster_offset & s->cluster_offset_mask) & ~511,
+                          nb_csectors * 512);
+        } else {
+            free_clusters(bs, cluster_offset, s->cluster_size);
+        }
+    } else {
+        cluster_offset &= ~QCOW_OFLAG_COPIED;
+        return cluster_offset;
+    }
+    if (allocate == 1) {
+        /* allocate a new cluster */
+        cluster_offset = alloc_clusters(bs, s->cluster_size);
+
+        /* we must initialize the cluster content which won't be
+           written */
+        if ((n_end - n_start) < s->cluster_sectors) {
+            uint64_t start_sect;
+            
+            start_sect = (offset & ~(s->cluster_size - 1)) >> 9;
+            ret = copy_sectors(bs, start_sect,
+                               cluster_offset, 0, n_start);
+            if (ret < 0)
+                return 0;
+            ret = copy_sectors(bs, start_sect,
+                               cluster_offset, n_end, s->cluster_sectors);
+            if (ret < 0)
+                return 0;
+        }
+        tmp = cpu_to_be64(cluster_offset | QCOW_OFLAG_COPIED);
+    } else {
+        int nb_csectors;
+        cluster_offset = alloc_bytes(bs, compressed_size);
+        nb_csectors = ((cluster_offset + compressed_size - 1) >> 9) - 
+            (cluster_offset >> 9);
+        cluster_offset |= QCOW_OFLAG_COMPRESSED | 
+            ((uint64_t)nb_csectors << s->csize_shift);
+        /* compressed clusters never have the copied flag */
+        tmp = cpu_to_be64(cluster_offset);
+    }
+    /* update L2 table */
+    l2_table[l2_index] = tmp;
+    if (bdrv_pwrite(s->hd, 
+                    l2_offset + l2_index * sizeof(tmp), &tmp, sizeof(tmp)) != sizeof(tmp))
+        return 0;
+    return cluster_offset;
+}
+
+static int qcow_is_allocated(BlockDriverState *bs, int64_t sector_num, 
+                             int nb_sectors, int *pnum)
+{
+    BDRVQcowState *s = bs->opaque;
+    int index_in_cluster, n;
+    uint64_t cluster_offset;
+
+    cluster_offset = get_cluster_offset(bs, sector_num << 9, 0, 0, 0, 0);
+    index_in_cluster = sector_num & (s->cluster_sectors - 1);
+    n = s->cluster_sectors - index_in_cluster;
+    if (n > nb_sectors)
+        n = nb_sectors;
+    *pnum = n;
+    return (cluster_offset != 0);
+}
+
+static int decompress_buffer(uint8_t *out_buf, int out_buf_size,
+                             const uint8_t *buf, int buf_size)
+{
+    z_stream strm1, *strm = &strm1;
+    int ret, out_len;
+
+    memset(strm, 0, sizeof(*strm));
+
+    strm->next_in = (uint8_t *)buf;
+    strm->avail_in = buf_size;
+    strm->next_out = out_buf;
+    strm->avail_out = out_buf_size;
+
+    ret = inflateInit2(strm, -12);
+    if (ret != Z_OK)
+        return -1;
+    ret = inflate(strm, Z_FINISH);
+    out_len = strm->next_out - out_buf;
+    if ((ret != Z_STREAM_END && ret != Z_BUF_ERROR) ||
+        out_len != out_buf_size) {
+        inflateEnd(strm);
+        return -1;
+    }
+    inflateEnd(strm);
+    return 0;
+}
+                              
+static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset)
+{
+    int ret, csize, nb_csectors, sector_offset;
+    uint64_t coffset;
+
+    coffset = cluster_offset & s->cluster_offset_mask;
+    if (s->cluster_cache_offset != coffset) {
+        nb_csectors = ((cluster_offset >> s->csize_shift) & s->csize_mask) + 1;
+        sector_offset = coffset & 511;
+        csize = nb_csectors * 512 - sector_offset;
+        ret = bdrv_read(s->hd, coffset >> 9, s->cluster_data, nb_csectors);
+        if (ret < 0) {
+            return -1;
+        }
+        if (decompress_buffer(s->cluster_cache, s->cluster_size,
+                              s->cluster_data + sector_offset, csize) < 0) {
+            return -1;
+        }
+        s->cluster_cache_offset = coffset;
+    }
+    return 0;
+}
+
+/* handle reading after the end of the backing file */
+static int backing_read1(BlockDriverState *bs, 
+                         int64_t sector_num, uint8_t *buf, int nb_sectors)
+{
+    int n1;
+    if ((sector_num + nb_sectors) <= bs->total_sectors)
+        return nb_sectors;
+    if (sector_num >= bs->total_sectors)
+        n1 = 0;
+    else
+        n1 = bs->total_sectors - sector_num;
+    memset(buf + n1 * 512, 0, 512 * (nb_sectors - n1));
+    return n1;
+}
+
+static int qcow_read(BlockDriverState *bs, int64_t sector_num, 
+                     uint8_t *buf, int nb_sectors)
+{
+    BDRVQcowState *s = bs->opaque;
+    int ret, index_in_cluster, n, n1;
+    uint64_t cluster_offset;
+    
+    while (nb_sectors > 0) {
+        cluster_offset = get_cluster_offset(bs, sector_num << 9, 0, 0, 0, 0);
+        index_in_cluster = sector_num & (s->cluster_sectors - 1);
+        n = s->cluster_sectors - index_in_cluster;
+        if (n > nb_sectors)
+            n = nb_sectors;
+        if (!cluster_offset) {
+            if (bs->backing_hd) {
+                /* read from the base image */
+                n1 = backing_read1(bs->backing_hd, sector_num, buf, n);
+                if (n1 > 0) {
+                    ret = bdrv_read(bs->backing_hd, sector_num, buf, n1);
+                    if (ret < 0)
+                        return -1;
+                }
+            } else {
+                memset(buf, 0, 512 * n);
+            }
+        } else if (cluster_offset & QCOW_OFLAG_COMPRESSED) {
+            if (decompress_cluster(s, cluster_offset) < 0)
+                return -1;
+            memcpy(buf, s->cluster_cache + index_in_cluster * 512, 512 * n);
+        } else {
+            ret = bdrv_pread(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512);
+            if (ret != n * 512) 
+                return -1;
+            if (s->crypt_method) {
+                encrypt_sectors(s, sector_num, buf, buf, n, 0, 
+                                &s->aes_decrypt_key);
+            }
+        }
+        nb_sectors -= n;
+        sector_num += n;
+        buf += n * 512;
+    }
+    return 0;
+}
+
+static int qcow_write(BlockDriverState *bs, int64_t sector_num, 
+                     const uint8_t *buf, int nb_sectors)
+{
+    BDRVQcowState *s = bs->opaque;
+    int ret, index_in_cluster, n;
+    uint64_t cluster_offset;
+    
+    while (nb_sectors > 0) {
+        index_in_cluster = sector_num & (s->cluster_sectors - 1);
+        n = s->cluster_sectors - index_in_cluster;
+        if (n > nb_sectors)
+            n = nb_sectors;
+        cluster_offset = get_cluster_offset(bs, sector_num << 9, 1, 0, 
+                                            index_in_cluster, 
+                                            index_in_cluster + n);
+        if (!cluster_offset)
+            return -1;
+        if (s->crypt_method) {
+            encrypt_sectors(s, sector_num, s->cluster_data, buf, n, 1,
+                            &s->aes_encrypt_key);
+            ret = bdrv_pwrite(s->hd, cluster_offset + index_in_cluster * 512, 
+                              s->cluster_data, n * 512);
+        } else {
+            ret = bdrv_pwrite(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512);
+        }
+        if (ret != n * 512) 
+            return -1;
+        nb_sectors -= n;
+        sector_num += n;
+        buf += n * 512;
+    }
+    s->cluster_cache_offset = -1; /* disable compressed cache */
+    return 0;
+}
+
+typedef struct QCowAIOCB {
+    BlockDriverAIOCB common;
+    int64_t sector_num;
+    uint8_t *buf;
+    int nb_sectors;
+    int n;
+    uint64_t cluster_offset;
+    uint8_t *cluster_data; 
+    BlockDriverAIOCB *hd_aiocb;
+} QCowAIOCB;
+
+static void qcow_aio_read_cb(void *opaque, int ret)
+{
+    QCowAIOCB *acb = opaque;
+    BlockDriverState *bs = acb->common.bs;
+    BDRVQcowState *s = bs->opaque;
+    int index_in_cluster, n1;
+
+    acb->hd_aiocb = NULL;
+    if (ret < 0) {
+    fail:
+        acb->common.cb(acb->common.opaque, ret);
+        qemu_aio_release(acb);
+        return;
+    }
+
+ redo:
+    /* post process the read buffer */
+    if (!acb->cluster_offset) {
+        /* nothing to do */
+    } else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) {
+        /* nothing to do */
+    } else {
+        if (s->crypt_method) {
+            encrypt_sectors(s, acb->sector_num, acb->buf, acb->buf, 
+                            acb->n, 0, 
+                            &s->aes_decrypt_key);
+        }
+    }
+
+    acb->nb_sectors -= acb->n;
+    acb->sector_num += acb->n;
+    acb->buf += acb->n * 512;
+
+    if (acb->nb_sectors == 0) {
+        /* request completed */
+        acb->common.cb(acb->common.opaque, 0);
+        qemu_aio_release(acb);
+        return;
+    }
+    
+    /* prepare next AIO request */
+    acb->cluster_offset = get_cluster_offset(bs, acb->sector_num << 9, 
+                                             0, 0, 0, 0);
+    index_in_cluster = acb->sector_num & (s->cluster_sectors - 1);
+    acb->n = s->cluster_sectors - index_in_cluster;
+    if (acb->n > acb->nb_sectors)
+        acb->n = acb->nb_sectors;
+
+    if (!acb->cluster_offset) {
+        if (bs->backing_hd) {
+            /* read from the base image */
+            n1 = backing_read1(bs->backing_hd, acb->sector_num, 
+                               acb->buf, acb->n);
+            if (n1 > 0) {
+                acb->hd_aiocb = bdrv_aio_read(bs->backing_hd, acb->sector_num, 
+                                    acb->buf, acb->n, qcow_aio_read_cb, acb);
+                if (acb->hd_aiocb == NULL)
+                    goto fail;
+            } else {
+                goto redo;
+            }
+        } else {
+            /* Note: in this case, no need to wait */
+            memset(acb->buf, 0, 512 * acb->n);
+            goto redo;
+        }
+    } else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) {
+        /* add AIO support for compressed blocks ? */
+        if (decompress_cluster(s, acb->cluster_offset) < 0)
+            goto fail;
+        memcpy(acb->buf, 
+               s->cluster_cache + index_in_cluster * 512, 512 * acb->n);
+        goto redo;
+    } else {
+        if ((acb->cluster_offset & 511) != 0) {
+            ret = -EIO;
+            goto fail;
+        }
+        acb->hd_aiocb = bdrv_aio_read(s->hd,
+                            (acb->cluster_offset >> 9) + index_in_cluster, 
+                            acb->buf, acb->n, qcow_aio_read_cb, acb);
+        if (acb->hd_aiocb == NULL)
+            goto fail;
+    }
+}
+
+static QCowAIOCB *qcow_aio_setup(BlockDriverState *bs,
+        int64_t sector_num, uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque)
+{
+    QCowAIOCB *acb;
+
+    acb = qemu_aio_get(bs, cb, opaque);
+    if (!acb)
+        return NULL;
+    acb->hd_aiocb = NULL;
+    acb->sector_num = sector_num;
+    acb->buf = buf;
+    acb->nb_sectors = nb_sectors;
+    acb->n = 0;
+    acb->cluster_offset = 0;
+    return acb;
+}
+
+static BlockDriverAIOCB *qcow_aio_read(BlockDriverState *bs,
+        int64_t sector_num, uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque)
+{
+    QCowAIOCB *acb;
+
+    acb = qcow_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
+    if (!acb)
+        return NULL;
+
+    qcow_aio_read_cb(acb, 0);
+    return &acb->common;
+}
+
+static void qcow_aio_write_cb(void *opaque, int ret)
+{
+    QCowAIOCB *acb = opaque;
+    BlockDriverState *bs = acb->common.bs;
+    BDRVQcowState *s = bs->opaque;
+    int index_in_cluster;
+    uint64_t cluster_offset;
+    const uint8_t *src_buf;
+
+    acb->hd_aiocb = NULL;
+
+    if (ret < 0) {
+    fail:
+        acb->common.cb(acb->common.opaque, ret);
+        qemu_aio_release(acb);
+        return;
+    }
+
+    acb->nb_sectors -= acb->n;
+    acb->sector_num += acb->n;
+    acb->buf += acb->n * 512;
+
+    if (acb->nb_sectors == 0) {
+        /* request completed */
+        acb->common.cb(acb->common.opaque, 0);
+        qemu_aio_release(acb);
+        return;
+    }
+    
+    index_in_cluster = acb->sector_num & (s->cluster_sectors - 1);
+    acb->n = s->cluster_sectors - index_in_cluster;
+    if (acb->n > acb->nb_sectors)
+        acb->n = acb->nb_sectors;
+    cluster_offset = get_cluster_offset(bs, acb->sector_num << 9, 1, 0, 
+                                        index_in_cluster, 
+                                        index_in_cluster + acb->n);
+    if (!cluster_offset || (cluster_offset & 511) != 0) {
+        ret = -EIO;
+        goto fail;
+    }
+    if (s->crypt_method) {
+        if (!acb->cluster_data) {
+            acb->cluster_data = qemu_mallocz(s->cluster_size);
+            if (!acb->cluster_data) {
+                ret = -ENOMEM;
+                goto fail;
+            }
+        }
+        encrypt_sectors(s, acb->sector_num, acb->cluster_data, acb->buf, 
+                        acb->n, 1, &s->aes_encrypt_key);
+        src_buf = acb->cluster_data;
+    } else {
+        src_buf = acb->buf;
+    }
+    acb->hd_aiocb = bdrv_aio_write(s->hd,
+                                   (cluster_offset >> 9) + index_in_cluster, 
+                                   src_buf, acb->n, 
+                                   qcow_aio_write_cb, acb);
+    if (acb->hd_aiocb == NULL)
+        goto fail;
+}
+
+static BlockDriverAIOCB *qcow_aio_write(BlockDriverState *bs,
+        int64_t sector_num, const uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque)
+{
+    BDRVQcowState *s = bs->opaque;
+    QCowAIOCB *acb;
+    
+    s->cluster_cache_offset = -1; /* disable compressed cache */
+
+    acb = qcow_aio_setup(bs, sector_num, (uint8_t*)buf, nb_sectors, cb, opaque);
+    if (!acb)
+        return NULL;
+    
+    qcow_aio_write_cb(acb, 0);
+    return &acb->common;
+}
+
+static void qcow_aio_cancel(BlockDriverAIOCB *blockacb)
+{
+    QCowAIOCB *acb = (QCowAIOCB *)blockacb;
+    if (acb->hd_aiocb)
+        bdrv_aio_cancel(acb->hd_aiocb);
+    qemu_aio_release(acb);
+}
+
+static void qcow_close(BlockDriverState *bs)
+{
+    BDRVQcowState *s = bs->opaque;
+    qemu_free(s->l1_table);
+    qemu_free(s->l2_cache);
+    qemu_free(s->cluster_cache);
+    qemu_free(s->cluster_data);
+    refcount_close(bs);
+    bdrv_delete(s->hd);
+}
+
+/* XXX: use std qcow open function ? */
+typedef struct QCowCreateState {
+    int cluster_size;
+    int cluster_bits;
+    uint16_t *refcount_block;
+    uint64_t *refcount_table;
+    int64_t l1_table_offset;
+    int64_t refcount_table_offset;
+    int64_t refcount_block_offset;
+} QCowCreateState;
+
+static void create_refcount_update(QCowCreateState *s,
+                                   int64_t offset, int64_t size)
+{
+    int refcount;
+    int64_t start, last, cluster_offset;
+    uint16_t *p;
+
+    start = offset & ~(s->cluster_size - 1);
+    last = (offset + size - 1)  & ~(s->cluster_size - 1);
+    for(cluster_offset = start; cluster_offset <= last; 
+        cluster_offset += s->cluster_size) {
+        p = &s->refcount_block[cluster_offset >> s->cluster_bits];
+        refcount = be16_to_cpu(*p);
+        refcount++;
+        *p = cpu_to_be16(refcount);
+    }
+}
+
+static int qcow_create(const char *filename, int64_t total_size,
+                      const char *backing_file, int flags)
+{
+    int fd, header_size, backing_filename_len, l1_size, i, shift, l2_bits;
+    QCowHeader header;
+    uint64_t tmp, offset;
+    QCowCreateState s1, *s = &s1;
+    
+    memset(s, 0, sizeof(*s));
+
+    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
+    if (fd < 0)
+        return -1;
+    memset(&header, 0, sizeof(header));
+    header.magic = cpu_to_be32(QCOW_MAGIC);
+    header.version = cpu_to_be32(QCOW_VERSION);
+    header.size = cpu_to_be64(total_size * 512);
+    header_size = sizeof(header);
+    backing_filename_len = 0;
+    if (backing_file) {
+        header.backing_file_offset = cpu_to_be64(header_size);
+        backing_filename_len = strlen(backing_file);
+        header.backing_file_size = cpu_to_be32(backing_filename_len);
+        header_size += backing_filename_len;
+    }
+    s->cluster_bits = 12;  /* 4 KB clusters */
+    s->cluster_size = 1 << s->cluster_bits;
+    header.cluster_bits = cpu_to_be32(s->cluster_bits);
+    header_size = (header_size + 7) & ~7;
+    if (flags) {
+        header.crypt_method = cpu_to_be32(QCOW_CRYPT_AES);
+    } else {
+        header.crypt_method = cpu_to_be32(QCOW_CRYPT_NONE);
+    }
+    l2_bits = s->cluster_bits - 3;
+    shift = s->cluster_bits + l2_bits;
+    l1_size = (((total_size * 512) + (1LL << shift) - 1) >> shift);
+    offset = align_offset(header_size, s->cluster_size);
+    s->l1_table_offset = offset;
+    header.l1_table_offset = cpu_to_be64(s->l1_table_offset);
+    header.l1_size = cpu_to_be32(l1_size);
+    offset += align_offset(l1_size * sizeof(uint64_t), s->cluster_size);
+
+    s->refcount_table = qemu_mallocz(s->cluster_size);
+    if (!s->refcount_table)
+        goto fail;
+    s->refcount_block = qemu_mallocz(s->cluster_size);
+    if (!s->refcount_block)
+        goto fail;
+    
+    s->refcount_table_offset = offset;
+    header.refcount_table_offset = cpu_to_be64(offset);
+    header.refcount_table_clusters = cpu_to_be32(1);
+    offset += s->cluster_size;
+
+    s->refcount_table[0] = cpu_to_be64(offset);
+    s->refcount_block_offset = offset;
+    offset += s->cluster_size;
+
+    /* update refcounts */
+    create_refcount_update(s, 0, header_size);
+    create_refcount_update(s, s->l1_table_offset, l1_size * sizeof(uint64_t));
+    create_refcount_update(s, s->refcount_table_offset, s->cluster_size);
+    create_refcount_update(s, s->refcount_block_offset, s->cluster_size);
+    
+    /* write all the data */
+    write(fd, &header, sizeof(header));
+    if (backing_file) {
+        write(fd, backing_file, backing_filename_len);
+    }
+    lseek(fd, s->l1_table_offset, SEEK_SET);
+    tmp = 0;
+    for(i = 0;i < l1_size; i++) {
+        write(fd, &tmp, sizeof(tmp));
+    }
+    lseek(fd, s->refcount_table_offset, SEEK_SET);
+    write(fd, s->refcount_table, s->cluster_size);
+    
+    lseek(fd, s->refcount_block_offset, SEEK_SET);
+    write(fd, s->refcount_block, s->cluster_size);
+
+    qemu_free(s->refcount_table);
+    qemu_free(s->refcount_block);
+    close(fd);
+    return 0;
+ fail:
+    qemu_free(s->refcount_table);
+    qemu_free(s->refcount_block);
+    close(fd);
+    return -ENOMEM;
+}
+
+static int qcow_make_empty(BlockDriverState *bs)
+{
+#if 0
+    /* XXX: not correct */
+    BDRVQcowState *s = bs->opaque;
+    uint32_t l1_length = s->l1_size * sizeof(uint64_t);
+    int ret;
+
+    memset(s->l1_table, 0, l1_length);
+    if (bdrv_pwrite(s->hd, s->l1_table_offset, s->l1_table, l1_length) < 0)
+       return -1;
+    ret = bdrv_truncate(s->hd, s->l1_table_offset + l1_length);
+    if (ret < 0)
+        return ret;
+    
+    l2_cache_reset(bs);
+#endif
+    return 0;
+}
+
+/* XXX: put compressed sectors first, then all the cluster aligned
+   tables to avoid losing bytes in alignment */
+static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num, 
+                                 const uint8_t *buf, int nb_sectors)
+{
+    BDRVQcowState *s = bs->opaque;
+    z_stream strm;
+    int ret, out_len;
+    uint8_t *out_buf;
+    uint64_t cluster_offset;
+
+    if (nb_sectors == 0) {
+        /* align end of file to a sector boundary to ease reading with
+           sector based I/Os */
+        cluster_offset = bdrv_getlength(s->hd);
+        cluster_offset = (cluster_offset + 511) & ~511;
+        bdrv_truncate(s->hd, cluster_offset);
+        return 0;
+    }
+
+    if (nb_sectors != s->cluster_sectors)
+        return -EINVAL;
+
+    out_buf = qemu_malloc(s->cluster_size + (s->cluster_size / 1000) + 128);
+    if (!out_buf)
+        return -ENOMEM;
+
+    /* best compression, small window, no zlib header */
+    memset(&strm, 0, sizeof(strm));
+    ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION,
+                       Z_DEFLATED, -12, 
+                       9, Z_DEFAULT_STRATEGY);
+    if (ret != 0) {
+        qemu_free(out_buf);
+        return -1;
+    }
+
+    strm.avail_in = s->cluster_size;
+    strm.next_in = (uint8_t *)buf;
+    strm.avail_out = s->cluster_size;
+    strm.next_out = out_buf;
+
+    ret = deflate(&strm, Z_FINISH);
+    if (ret != Z_STREAM_END && ret != Z_OK) {
+        qemu_free(out_buf);
+        deflateEnd(&strm);
+        return -1;
+    }
+    out_len = strm.next_out - out_buf;
+
+    deflateEnd(&strm);
+
+    if (ret != Z_STREAM_END || out_len >= s->cluster_size) {
+        /* could not compress: write normal cluster */
+        qcow_write(bs, sector_num, buf, s->cluster_sectors);
+    } else {
+        cluster_offset = get_cluster_offset(bs, sector_num << 9, 2, 
+                                            out_len, 0, 0);
+        cluster_offset &= s->cluster_offset_mask;
+        if (bdrv_pwrite(s->hd, cluster_offset, out_buf, out_len) != out_len) {
+            qemu_free(out_buf);
+            return -1;
+        }
+    }
+    
+    qemu_free(out_buf);
+    return 0;
+}
+
+static void qcow_flush(BlockDriverState *bs)
+{
+    BDRVQcowState *s = bs->opaque;
+    bdrv_flush(s->hd);
+}
+
+static int qcow_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
+{
+    BDRVQcowState *s = bs->opaque;
+    bdi->cluster_size = s->cluster_size;
+    bdi->vm_state_offset = (int64_t)s->l1_vm_state_index << 
+        (s->cluster_bits + s->l2_bits);
+    return 0;
+}
+
+/*********************************************************/
+/* snapshot support */
+
+/* update the refcounts of snapshots and the copied flag */
+static int update_snapshot_refcount(BlockDriverState *bs, 
+                                    int64_t l1_table_offset,
+                                    int l1_size,
+                                    int addend)
+{
+    BDRVQcowState *s = bs->opaque;
+    uint64_t *l1_table, *l2_table, l2_offset, offset, l1_size2, l1_allocated;
+    int64_t old_offset, old_l2_offset;
+    int l2_size, i, j, l1_modified, l2_modified, nb_csectors, refcount;
+    
+    l2_cache_reset(bs);
+
+    l2_table = NULL;
+    l1_table = NULL;
+    l1_size2 = l1_size * sizeof(uint64_t);
+    l1_allocated = 0;
+    if (l1_table_offset != s->l1_table_offset) {
+        l1_table = qemu_malloc(l1_size2);
+        if (!l1_table)
+            goto fail;
+        l1_allocated = 1;
+        if (bdrv_pread(s->hd, l1_table_offset, 
+                       l1_table, l1_size2) != l1_size2)
+            goto fail;
+        for(i = 0;i < l1_size; i++)
+            be64_to_cpus(&l1_table[i]);
+    } else {
+        assert(l1_size == s->l1_size);
+        l1_table = s->l1_table;
+        l1_allocated = 0;
+    }
+    
+    l2_size = s->l2_size * sizeof(uint64_t);
+    l2_table = qemu_malloc(l2_size);
+    if (!l2_table)
+        goto fail;
+    l1_modified = 0;
+    for(i = 0; i < l1_size; i++) {
+        l2_offset = l1_table[i];
+        if (l2_offset) {
+            old_l2_offset = l2_offset;
+            l2_offset &= ~QCOW_OFLAG_COPIED;
+            l2_modified = 0;
+            if (bdrv_pread(s->hd, l2_offset, l2_table, l2_size) != l2_size)
+                goto fail;
+            for(j = 0; j < s->l2_size; j++) {
+                offset = be64_to_cpu(l2_table[j]);
+                if (offset != 0) {
+                    old_offset = offset;
+                    offset &= ~QCOW_OFLAG_COPIED;
+                    if (offset & QCOW_OFLAG_COMPRESSED) {
+                        nb_csectors = ((offset >> s->csize_shift) & 
+                                       s->csize_mask) + 1;
+                        if (addend != 0)
+                            update_refcount(bs, (offset & s->cluster_offset_mask) & ~511,
+                                            nb_csectors * 512, addend);
+                        /* compressed clusters are never modified */
+                        refcount = 2; 
+                    } else {
+                        if (addend != 0) {
+                            refcount = update_cluster_refcount(bs, offset >> s->cluster_bits, addend);
+                        } else {
+                            refcount = get_refcount(bs, offset >> s->cluster_bits);
+                        }
+                    }
+
+                    if (refcount == 1) {
+                        offset |= QCOW_OFLAG_COPIED;
+                    }
+                    if (offset != old_offset) {
+                        l2_table[j] = cpu_to_be64(offset);
+                        l2_modified = 1;
+                    }
+                }
+            }
+            if (l2_modified) {
+                if (bdrv_pwrite(s->hd, 
+                                l2_offset, l2_table, l2_size) != l2_size)
+                    goto fail;
+            }
+
+            if (addend != 0) {
+                refcount = update_cluster_refcount(bs, l2_offset >> s->cluster_bits, addend);
+            } else {
+                refcount = get_refcount(bs, l2_offset >> s->cluster_bits);
+            }
+            if (refcount == 1) {
+                l2_offset |= QCOW_OFLAG_COPIED;
+            }
+            if (l2_offset != old_l2_offset) {
+                l1_table[i] = l2_offset;
+                l1_modified = 1;
+            }
+        }
+    }
+    if (l1_modified) {
+        for(i = 0; i < l1_size; i++)
+            cpu_to_be64s(&l1_table[i]);
+        if (bdrv_pwrite(s->hd, l1_table_offset, l1_table, 
+                        l1_size2) != l1_size2)
+            goto fail;
+        for(i = 0; i < l1_size; i++)
+            be64_to_cpus(&l1_table[i]);
+    }
+    if (l1_allocated)
+        qemu_free(l1_table);
+    qemu_free(l2_table);
+    return 0;
+ fail:
+    if (l1_allocated)
+        qemu_free(l1_table);
+    qemu_free(l2_table);
+    return -EIO;
+}
+
+static void qcow_free_snapshots(BlockDriverState *bs)
+{
+    BDRVQcowState *s = bs->opaque;
+    int i;
+
+    for(i = 0; i < s->nb_snapshots; i++) {
+        qemu_free(s->snapshots[i].name);
+        qemu_free(s->snapshots[i].id_str);
+    }
+    qemu_free(s->snapshots);
+    s->snapshots = NULL;
+    s->nb_snapshots = 0;
+}
+
+static int qcow_read_snapshots(BlockDriverState *bs)
+{
+    BDRVQcowState *s = bs->opaque;
+    QCowSnapshotHeader h;
+    QCowSnapshot *sn;
+    int i, id_str_size, name_size;
+    int64_t offset;
+    uint32_t extra_data_size;
+
+    offset = s->snapshots_offset;
+    s->snapshots = qemu_mallocz(s->nb_snapshots * sizeof(QCowSnapshot));
+    if (!s->snapshots)
+        goto fail;
+    for(i = 0; i < s->nb_snapshots; i++) {
+        offset = align_offset(offset, 8);
+        if (bdrv_pread(s->hd, offset, &h, sizeof(h)) != sizeof(h))
+            goto fail;
+        offset += sizeof(h);
+        sn = s->snapshots + i;
+        sn->l1_table_offset = be64_to_cpu(h.l1_table_offset);
+        sn->l1_size = be32_to_cpu(h.l1_size);
+        sn->vm_state_size = be32_to_cpu(h.vm_state_size);
+        sn->date_sec = be32_to_cpu(h.date_sec);
+        sn->date_nsec = be32_to_cpu(h.date_nsec);
+        sn->vm_clock_nsec = be64_to_cpu(h.vm_clock_nsec);
+        extra_data_size = be32_to_cpu(h.extra_data_size);
+
+        id_str_size = be16_to_cpu(h.id_str_size);
+        name_size = be16_to_cpu(h.name_size);
+
+        offset += extra_data_size;
+
+        sn->id_str = qemu_malloc(id_str_size + 1);
+        if (!sn->id_str)
+            goto fail;
+        if (bdrv_pread(s->hd, offset, sn->id_str, id_str_size) != id_str_size)
+            goto fail;
+        offset += id_str_size;
+        sn->id_str[id_str_size] = '\0';
+
+        sn->name = qemu_malloc(name_size + 1);
+        if (!sn->name)
+            goto fail;
+        if (bdrv_pread(s->hd, offset, sn->name, name_size) != name_size)
+            goto fail;
+        offset += name_size;
+        sn->name[name_size] = '\0';
+    }
+    s->snapshots_size = offset - s->snapshots_offset;
+    return 0;
+ fail:
+    qcow_free_snapshots(bs);
+    return -1;
+}
+
+/* add at the end of the file a new list of snapshots */
+static int qcow_write_snapshots(BlockDriverState *bs)
+{
+    BDRVQcowState *s = bs->opaque;
+    QCowSnapshot *sn;
+    QCowSnapshotHeader h;
+    int i, name_size, id_str_size, snapshots_size;
+    uint64_t data64;
+    uint32_t data32;
+    int64_t offset, snapshots_offset;
+
+    /* compute the size of the snapshots */
+    offset = 0;
+    for(i = 0; i < s->nb_snapshots; i++) {
+        sn = s->snapshots + i;
+        offset = align_offset(offset, 8);
+        offset += sizeof(h);
+        offset += strlen(sn->id_str);
+        offset += strlen(sn->name);
+    }
+    snapshots_size = offset;
+
+    snapshots_offset = alloc_clusters(bs, snapshots_size);
+    offset = snapshots_offset;
+    
+    for(i = 0; i < s->nb_snapshots; i++) {
+        sn = s->snapshots + i;
+        memset(&h, 0, sizeof(h));
+        h.l1_table_offset = cpu_to_be64(sn->l1_table_offset);
+        h.l1_size = cpu_to_be32(sn->l1_size);
+        h.vm_state_size = cpu_to_be32(sn->vm_state_size);
+        h.date_sec = cpu_to_be32(sn->date_sec);
+        h.date_nsec = cpu_to_be32(sn->date_nsec);
+        h.vm_clock_nsec = cpu_to_be64(sn->vm_clock_nsec);
+        
+        id_str_size = strlen(sn->id_str);
+        name_size = strlen(sn->name);
+        h.id_str_size = cpu_to_be16(id_str_size);
+        h.name_size = cpu_to_be16(name_size);
+        offset = align_offset(offset, 8);
+        if (bdrv_pwrite(s->hd, offset, &h, sizeof(h)) != sizeof(h))
+            goto fail;
+        offset += sizeof(h);
+        if (bdrv_pwrite(s->hd, offset, sn->id_str, id_str_size) != id_str_size)
+            goto fail;
+        offset += id_str_size;
+        if (bdrv_pwrite(s->hd, offset, sn->name, name_size) != name_size)
+            goto fail;
+        offset += name_size;
+    }
+
+    /* update the various header fields */
+    data64 = cpu_to_be64(snapshots_offset);
+    if (bdrv_pwrite(s->hd, offsetof(QCowHeader, snapshots_offset),
+                    &data64, sizeof(data64)) != sizeof(data64))
+        goto fail;
+    data32 = cpu_to_be32(s->nb_snapshots);
+    if (bdrv_pwrite(s->hd, offsetof(QCowHeader, nb_snapshots),
+                    &data32, sizeof(data32)) != sizeof(data32))
+        goto fail;
+
+    /* free the old snapshot table */
+    free_clusters(bs, s->snapshots_offset, s->snapshots_size);
+    s->snapshots_offset = snapshots_offset;
+    s->snapshots_size = snapshots_size;
+    return 0;
+ fail:
+    return -1;
+}
+
+static void find_new_snapshot_id(BlockDriverState *bs,
+                                 char *id_str, int id_str_size)
+{
+    BDRVQcowState *s = bs->opaque;
+    QCowSnapshot *sn;
+    int i, id, id_max = 0;
+
+    for(i = 0; i < s->nb_snapshots; i++) {
+        sn = s->snapshots + i;
+        id = strtoul(sn->id_str, NULL, 10);
+        if (id > id_max)
+            id_max = id;
+    }
+    snprintf(id_str, id_str_size, "%d", id_max + 1);
+}
+
+static int find_snapshot_by_id(BlockDriverState *bs, const char *id_str)
+{
+    BDRVQcowState *s = bs->opaque;
+    int i;
+
+    for(i = 0; i < s->nb_snapshots; i++) {
+        if (!strcmp(s->snapshots[i].id_str, id_str))
+            return i;
+    }
+    return -1;
+}
+
+static int find_snapshot_by_id_or_name(BlockDriverState *bs, const char *name)
+{
+    BDRVQcowState *s = bs->opaque;
+    int i, ret;
+    
+    ret = find_snapshot_by_id(bs, name);
+    if (ret >= 0)
+        return ret;
+    for(i = 0; i < s->nb_snapshots; i++) {
+        if (!strcmp(s->snapshots[i].name, name))
+            return i;
+    }
+    return -1;
+}
+
+/* if no id is provided, a new one is constructed */
+static int qcow_snapshot_create(BlockDriverState *bs, 
+                                QEMUSnapshotInfo *sn_info)
+{
+    BDRVQcowState *s = bs->opaque;
+    QCowSnapshot *snapshots1, sn1, *sn = &sn1;
+    int i, ret;
+    uint64_t *l1_table = NULL;
+    
+    memset(sn, 0, sizeof(*sn));
+
+    if (sn_info->id_str[0] == '\0') {
+        /* compute a new id */
+        find_new_snapshot_id(bs, sn_info->id_str, sizeof(sn_info->id_str));
+    }
+
+    /* check that the ID is unique */
+    if (find_snapshot_by_id(bs, sn_info->id_str) >= 0)
+        return -ENOENT;
+
+    sn->id_str = qemu_strdup(sn_info->id_str);
+    if (!sn->id_str)
+        goto fail;
+    sn->name = qemu_strdup(sn_info->name);
+    if (!sn->name)
+        goto fail;
+    sn->vm_state_size = sn_info->vm_state_size;
+    sn->date_sec = sn_info->date_sec;
+    sn->date_nsec = sn_info->date_nsec;
+    sn->vm_clock_nsec = sn_info->vm_clock_nsec;
+
+    ret = update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, 1);
+    if (ret < 0)
+        goto fail;
+
+    /* create the L1 table of the snapshot */
+    sn->l1_table_offset = alloc_clusters(bs, s->l1_size * sizeof(uint64_t));
+    sn->l1_size = s->l1_size;
+
+    l1_table = qemu_malloc(s->l1_size * sizeof(uint64_t));
+    if (!l1_table)
+        goto fail;
+    for(i = 0; i < s->l1_size; i++) {
+        l1_table[i] = cpu_to_be64(s->l1_table[i]);
+    }
+    if (bdrv_pwrite(s->hd, sn->l1_table_offset,
+                    l1_table, s->l1_size * sizeof(uint64_t)) != 
+        (s->l1_size * sizeof(uint64_t)))
+        goto fail;
+    qemu_free(l1_table);
+    l1_table = NULL;
+
+    snapshots1 = qemu_malloc((s->nb_snapshots + 1) * sizeof(QCowSnapshot));
+    if (!snapshots1)
+        goto fail;
+    memcpy(snapshots1, s->snapshots, s->nb_snapshots * sizeof(QCowSnapshot));
+    s->snapshots = snapshots1;
+    s->snapshots[s->nb_snapshots++] = *sn;
+
+    if (qcow_write_snapshots(bs) < 0)
+        goto fail;
+#ifdef DEBUG_ALLOC
+    check_refcounts(bs);
+#endif
+    return 0;
+ fail:
+    qemu_free(sn->name);
+    qemu_free(l1_table);
+    return -1;
+}
+
+/* copy the snapshot 'snapshot_name' into the current disk image */
+static int qcow_snapshot_goto(BlockDriverState *bs, 
+                              const char *snapshot_id)
+{
+    BDRVQcowState *s = bs->opaque;
+    QCowSnapshot *sn;
+    int i, snapshot_index, l1_size2;
+
+    snapshot_index = find_snapshot_by_id_or_name(bs, snapshot_id);
+    if (snapshot_index < 0)
+        return -ENOENT;
+    sn = &s->snapshots[snapshot_index];
+
+    if (update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, -1) < 0)
+        goto fail;
+
+    if (grow_l1_table(bs, sn->l1_size) < 0)
+        goto fail;
+
+    s->l1_size = sn->l1_size;
+    l1_size2 = s->l1_size * sizeof(uint64_t);
+    /* copy the snapshot l1 table to the current l1 table */
+    if (bdrv_pread(s->hd, sn->l1_table_offset, 
+                   s->l1_table, l1_size2) != l1_size2)
+        goto fail;
+    if (bdrv_pwrite(s->hd, s->l1_table_offset,
+                    s->l1_table, l1_size2) != l1_size2)
+        goto fail;
+    for(i = 0;i < s->l1_size; i++) {
+        be64_to_cpus(&s->l1_table[i]);
+    }
+
+    if (update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, 1) < 0)
+        goto fail;
+
+#ifdef DEBUG_ALLOC
+    check_refcounts(bs);
+#endif
+    return 0;
+ fail:
+    return -EIO;
+}
+
+static int qcow_snapshot_delete(BlockDriverState *bs, const char *snapshot_id)
+{
+    BDRVQcowState *s = bs->opaque;
+    QCowSnapshot *sn;
+    int snapshot_index, ret;
+    
+    snapshot_index = find_snapshot_by_id_or_name(bs, snapshot_id);
+    if (snapshot_index < 0)
+        return -ENOENT;
+    sn = &s->snapshots[snapshot_index];
+
+    ret = update_snapshot_refcount(bs, sn->l1_table_offset, sn->l1_size, -1);
+    if (ret < 0)
+        return ret;
+    /* must update the copied flag on the current cluster offsets */
+    ret = update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, 0);
+    if (ret < 0)
+        return ret;
+    free_clusters(bs, sn->l1_table_offset, sn->l1_size * sizeof(uint64_t));
+
+    qemu_free(sn->id_str);
+    qemu_free(sn->name);
+    memmove(sn, sn + 1, (s->nb_snapshots - snapshot_index - 1) * sizeof(*sn));
+    s->nb_snapshots--;
+    ret = qcow_write_snapshots(bs);
+    if (ret < 0) {
+        /* XXX: restore snapshot if error ? */
+        return ret;
+    }
+#ifdef DEBUG_ALLOC
+    check_refcounts(bs);
+#endif
+    return 0;
+}
+
+static int qcow_snapshot_list(BlockDriverState *bs, 
+                              QEMUSnapshotInfo **psn_tab)
+{
+    BDRVQcowState *s = bs->opaque;
+    QEMUSnapshotInfo *sn_tab, *sn_info;
+    QCowSnapshot *sn;
+    int i;
+
+    sn_tab = qemu_mallocz(s->nb_snapshots * sizeof(QEMUSnapshotInfo));
+    if (!sn_tab)
+        goto fail;
+    for(i = 0; i < s->nb_snapshots; i++) {
+        sn_info = sn_tab + i;
+        sn = s->snapshots + i;
+        pstrcpy(sn_info->id_str, sizeof(sn_info->id_str),
+                sn->id_str);
+        pstrcpy(sn_info->name, sizeof(sn_info->name),
+                sn->name);
+        sn_info->vm_state_size = sn->vm_state_size;
+        sn_info->date_sec = sn->date_sec;
+        sn_info->date_nsec = sn->date_nsec;
+        sn_info->vm_clock_nsec = sn->vm_clock_nsec;
+    }
+    *psn_tab = sn_tab;
+    return s->nb_snapshots;
+ fail:
+    qemu_free(sn_tab);
+    *psn_tab = NULL;
+    return -ENOMEM;
+}
+
+/*********************************************************/
+/* refcount handling */
+
+static int refcount_init(BlockDriverState *bs)
+{
+    BDRVQcowState *s = bs->opaque;
+    int ret, refcount_table_size2, i;
+    
+    s->refcount_block_cache = qemu_malloc(s->cluster_size);
+    if (!s->refcount_block_cache)
+        goto fail;
+    refcount_table_size2 = s->refcount_table_size * sizeof(uint64_t);
+    s->refcount_table = qemu_malloc(refcount_table_size2);
+    if (!s->refcount_table)
+        goto fail;
+    if (s->refcount_table_size > 0) {
+        ret = bdrv_pread(s->hd, s->refcount_table_offset,
+                         s->refcount_table, refcount_table_size2);
+        if (ret != refcount_table_size2)
+            goto fail;
+        for(i = 0; i < s->refcount_table_size; i++)
+            be64_to_cpus(&s->refcount_table[i]);
+    }
+    return 0;
+ fail:
+    return -ENOMEM;
+}
+
+static void refcount_close(BlockDriverState *bs)
+{
+    BDRVQcowState *s = bs->opaque;
+    qemu_free(s->refcount_block_cache);
+    qemu_free(s->refcount_table);
+}
+
+
+static int load_refcount_block(BlockDriverState *bs, 
+                               int64_t refcount_block_offset)
+{
+    BDRVQcowState *s = bs->opaque;
+    int ret;
+    ret = bdrv_pread(s->hd, refcount_block_offset, s->refcount_block_cache, 
+                     s->cluster_size);
+    if (ret != s->cluster_size)
+        return -EIO;
+    s->refcount_block_cache_offset = refcount_block_offset;
+    return 0;
+}
+
+static int get_refcount(BlockDriverState *bs, int64_t cluster_index)
+{
+    BDRVQcowState *s = bs->opaque;
+    int refcount_table_index, block_index;
+    int64_t refcount_block_offset;
+
+    refcount_table_index = cluster_index >> (s->cluster_bits - REFCOUNT_SHIFT);
+    if (refcount_table_index >= s->refcount_table_size)
+        return 0;
+    refcount_block_offset = s->refcount_table[refcount_table_index];
+    if (!refcount_block_offset)
+        return 0;
+    if (refcount_block_offset != s->refcount_block_cache_offset) {
+        /* better than nothing: return allocated if read error */
+        if (load_refcount_block(bs, refcount_block_offset) < 0)
+            return 1;
+    }
+    block_index = cluster_index & 
+        ((1 << (s->cluster_bits - REFCOUNT_SHIFT)) - 1);
+    return be16_to_cpu(s->refcount_block_cache[block_index]);
+}
+
+/* return < 0 if error */
+static int64_t alloc_clusters_noref(BlockDriverState *bs, int64_t size)
+{
+    BDRVQcowState *s = bs->opaque;
+    int i, nb_clusters;
+
+    nb_clusters = (size + s->cluster_size - 1) >> s->cluster_bits;
+    for(;;) {
+        if (get_refcount(bs, s->free_cluster_index) == 0) {
+            s->free_cluster_index++;
+            for(i = 1; i < nb_clusters; i++) {
+                if (get_refcount(bs, s->free_cluster_index) != 0)
+                    goto not_found;
+                s->free_cluster_index++;
+            }
+#ifdef DEBUG_ALLOC2
+            printf("alloc_clusters: size=%lld -> %lld\n",
+                   size, 
+                   (s->free_cluster_index - nb_clusters) << s->cluster_bits);
+#endif
+            return (s->free_cluster_index - nb_clusters) << s->cluster_bits;
+        } else {
+        not_found:
+            s->free_cluster_index++;
+        }
+    }
+}
+
+static int64_t alloc_clusters(BlockDriverState *bs, int64_t size)
+{
+    int64_t offset;
+
+    offset = alloc_clusters_noref(bs, size);
+    update_refcount(bs, offset, size, 1);
+    return offset;
+}
+
+/* only used to allocate compressed sectors. We try to allocate
+   contiguous sectors. size must be <= cluster_size */
+static int64_t alloc_bytes(BlockDriverState *bs, int size)
+{
+    BDRVQcowState *s = bs->opaque;
+    int64_t offset, cluster_offset;
+    int free_in_cluster;
+    
+    assert(size > 0 && size <= s->cluster_size);
+    if (s->free_byte_offset == 0) {
+        s->free_byte_offset = alloc_clusters(bs, s->cluster_size);
+    }
+ redo:
+    free_in_cluster = s->cluster_size - 
+        (s->free_byte_offset & (s->cluster_size - 1));
+    if (size <= free_in_cluster) {
+        /* enough space in current cluster */
+        offset = s->free_byte_offset;
+        s->free_byte_offset += size;
+        free_in_cluster -= size;
+        if (free_in_cluster == 0)
+            s->free_byte_offset = 0;
+        if ((offset & (s->cluster_size - 1)) != 0)
+            update_cluster_refcount(bs, offset >> s->cluster_bits, 1);
+    } else {
+        offset = alloc_clusters(bs, s->cluster_size);
+        cluster_offset = s->free_byte_offset & ~(s->cluster_size - 1);
+        if ((cluster_offset + s->cluster_size) == offset) {
+            /* we are lucky: contiguous data */
+            offset = s->free_byte_offset;
+            update_cluster_refcount(bs, offset >> s->cluster_bits, 1);
+            s->free_byte_offset += size;
+        } else {
+            s->free_byte_offset = offset;
+            goto redo;
+        }
+    }
+    return offset;
+}
+
+static void free_clusters(BlockDriverState *bs, 
+                          int64_t offset, int64_t size)
+{
+    update_refcount(bs, offset, size, -1);
+}
+
+static int grow_refcount_table(BlockDriverState *bs, int min_size)
+{
+    BDRVQcowState *s = bs->opaque;
+    int new_table_size, new_table_size2, refcount_table_clusters, i, ret;
+    uint64_t *new_table;
+    int64_t table_offset;
+    uint64_t data64;
+    uint32_t data32;
+
+    if (min_size <= s->refcount_table_size)
+        return 0;
+    /* compute new table size */
+    refcount_table_clusters = s->refcount_table_size >> (s->cluster_bits - 3);
+    for(;;) {
+        if (refcount_table_clusters == 0) {
+            refcount_table_clusters = 1;
+        } else {
+            refcount_table_clusters = (refcount_table_clusters * 3 + 1) / 2;
+        }
+        new_table_size = refcount_table_clusters << (s->cluster_bits - 3);
+        if (min_size <= new_table_size)
+            break;
+    }
+#ifdef DEBUG_ALLOC2
+    printf("grow_refcount_table from %d to %d\n",
+           s->refcount_table_size,
+           new_table_size);
+#endif
+    new_table_size2 = new_table_size * sizeof(uint64_t);
+    new_table = qemu_mallocz(new_table_size2);
+    if (!new_table)
+        return -ENOMEM;
+    memcpy(new_table, s->refcount_table, 
+           s->refcount_table_size * sizeof(uint64_t));
+    for(i = 0; i < s->refcount_table_size; i++)
+        cpu_to_be64s(&new_table[i]);
+    /* Note: we cannot update the refcount now to avoid recursion */
+    table_offset = alloc_clusters_noref(bs, new_table_size2);
+    ret = bdrv_pwrite(s->hd, table_offset, new_table, new_table_size2);
+    if (ret != new_table_size2) 
+        goto fail;
+    for(i = 0; i < s->refcount_table_size; i++)
+        be64_to_cpus(&new_table[i]);
+
+    data64 = cpu_to_be64(table_offset);
+    if (bdrv_pwrite(s->hd, offsetof(QCowHeader, refcount_table_offset),
+                    &data64, sizeof(data64)) != sizeof(data64))
+        goto fail;
+    data32 = cpu_to_be32(refcount_table_clusters);
+    if (bdrv_pwrite(s->hd, offsetof(QCowHeader, refcount_table_clusters),
+                    &data32, sizeof(data32)) != sizeof(data32))
+        goto fail;
+    qemu_free(s->refcount_table);
+    s->refcount_table = new_table;
+    s->refcount_table_size = new_table_size;
+
+    update_refcount(bs, table_offset, new_table_size2, 1);
+    return 0;
+ fail:
+    free_clusters(bs, table_offset, new_table_size2);
+    qemu_free(new_table);
+    return -EIO;
+}
+
+/* addend must be 1 or -1 */
+/* XXX: cache several refcount block clusters ? */
+static int update_cluster_refcount(BlockDriverState *bs, 
+                                   int64_t cluster_index,
+                                   int addend)
+{
+    BDRVQcowState *s = bs->opaque;
+    int64_t offset, refcount_block_offset;
+    int ret, refcount_table_index, block_index, refcount;
+    uint64_t data64;
+
+    refcount_table_index = cluster_index >> (s->cluster_bits - REFCOUNT_SHIFT);
+    if (refcount_table_index >= s->refcount_table_size) {
+        if (addend < 0)
+            return -EINVAL;
+        ret = grow_refcount_table(bs, refcount_table_index + 1);
+        if (ret < 0)
+            return ret;
+    }
+    refcount_block_offset = s->refcount_table[refcount_table_index];
+    if (!refcount_block_offset) {
+        if (addend < 0)
+            return -EINVAL;
+        /* create a new refcount block */
+        /* Note: we cannot update the refcount now to avoid recursion */
+        offset = alloc_clusters_noref(bs, s->cluster_size);
+        memset(s->refcount_block_cache, 0, s->cluster_size);
+        ret = bdrv_pwrite(s->hd, offset, s->refcount_block_cache, s->cluster_size);
+        if (ret != s->cluster_size)
+            return -EINVAL;
+        s->refcount_table[refcount_table_index] = offset;
+        data64 = cpu_to_be64(offset);
+        ret = bdrv_pwrite(s->hd, s->refcount_table_offset + 
+                          refcount_table_index * sizeof(uint64_t), 
+                          &data64, sizeof(data64));
+        if (ret != sizeof(data64))
+            return -EINVAL;
+
+        refcount_block_offset = offset;
+        s->refcount_block_cache_offset = offset;
+        update_refcount(bs, offset, s->cluster_size, 1);
+    } else {
+        if (refcount_block_offset != s->refcount_block_cache_offset) {
+            if (load_refcount_block(bs, refcount_block_offset) < 0)
+                return -EIO;
+        }
+    }
+    /* we can update the count and save it */
+    block_index = cluster_index & 
+        ((1 << (s->cluster_bits - REFCOUNT_SHIFT)) - 1);
+    refcount = be16_to_cpu(s->refcount_block_cache[block_index]);
+    refcount += addend;
+    if (refcount < 0 || refcount > 0xffff)
+        return -EINVAL;
+    if (refcount == 0 && cluster_index < s->free_cluster_index) {
+        s->free_cluster_index = cluster_index;
+    }
+    s->refcount_block_cache[block_index] = cpu_to_be16(refcount);
+    if (bdrv_pwrite(s->hd, 
+                    refcount_block_offset + (block_index << REFCOUNT_SHIFT), 
+                    &s->refcount_block_cache[block_index], 2) != 2)
+        return -EIO;
+    return refcount;
+}
+
+static void update_refcount(BlockDriverState *bs, 
+                            int64_t offset, int64_t length, 
+                            int addend)
+{
+    BDRVQcowState *s = bs->opaque;
+    int64_t start, last, cluster_offset;
+
+#ifdef DEBUG_ALLOC2
+    printf("update_refcount: offset=%lld size=%lld addend=%d\n", 
+           offset, length, addend);
+#endif
+    if (length <= 0)
+        return;
+    start = offset & ~(s->cluster_size - 1);
+    last = (offset + length - 1) & ~(s->cluster_size - 1);
+    for(cluster_offset = start; cluster_offset <= last; 
+        cluster_offset += s->cluster_size) {
+        update_cluster_refcount(bs, cluster_offset >> s->cluster_bits, addend);
+    }
+}
+
+#ifdef DEBUG_ALLOC
+static void inc_refcounts(BlockDriverState *bs, 
+                          uint16_t *refcount_table, 
+                          int refcount_table_size,
+                          int64_t offset, int64_t size)
+{
+    BDRVQcowState *s = bs->opaque;
+    int64_t start, last, cluster_offset;
+    int k;
+    
+    if (size <= 0)
+        return;
+
+    start = offset & ~(s->cluster_size - 1);
+    last = (offset + size - 1) & ~(s->cluster_size - 1);
+    for(cluster_offset = start; cluster_offset <= last; 
+        cluster_offset += s->cluster_size) {
+        k = cluster_offset >> s->cluster_bits;
+        if (k < 0 || k >= refcount_table_size) {
+            printf("ERROR: invalid cluster offset=0x%llx\n", cluster_offset);
+        } else {
+            if (++refcount_table[k] == 0) {
+                printf("ERROR: overflow cluster offset=0x%llx\n", cluster_offset);
+            }
+        }
+    }
+}
+
+static int check_refcounts_l1(BlockDriverState *bs, 
+                              uint16_t *refcount_table, 
+                              int refcount_table_size,
+                              int64_t l1_table_offset, int l1_size,
+                              int check_copied)
+{
+    BDRVQcowState *s = bs->opaque;
+    uint64_t *l1_table, *l2_table, l2_offset, offset, l1_size2;
+    int l2_size, i, j, nb_csectors, refcount;
+
+    l2_table = NULL;
+    l1_size2 = l1_size * sizeof(uint64_t);
+
+    inc_refcounts(bs, refcount_table, refcount_table_size,
+                  l1_table_offset, l1_size2);
+
+    l1_table = qemu_malloc(l1_size2);
+    if (!l1_table)
+        goto fail;
+    if (bdrv_pread(s->hd, l1_table_offset, 
+                   l1_table, l1_size2) != l1_size2)
+        goto fail;
+    for(i = 0;i < l1_size; i++)
+        be64_to_cpus(&l1_table[i]);
+    
+    l2_size = s->l2_size * sizeof(uint64_t);
+    l2_table = qemu_malloc(l2_size);
+    if (!l2_table)
+        goto fail;
+    for(i = 0; i < l1_size; i++) {
+        l2_offset = l1_table[i];
+        if (l2_offset) {
+            if (check_copied) {
+                refcount = get_refcount(bs, (l2_offset & ~QCOW_OFLAG_COPIED) >> s->cluster_bits);
+                if ((refcount == 1) != ((l2_offset & QCOW_OFLAG_COPIED) != 0)) {
+                    printf("ERROR OFLAG_COPIED: l2_offset=%llx refcount=%d\n",
+                           l2_offset, refcount);
+                }
+            }
+            l2_offset &= ~QCOW_OFLAG_COPIED;
+            if (bdrv_pread(s->hd, l2_offset, l2_table, l2_size) != l2_size)
+                goto fail;
+            for(j = 0; j < s->l2_size; j++) {
+                offset = be64_to_cpu(l2_table[j]);
+                if (offset != 0) {
+                    if (offset & QCOW_OFLAG_COMPRESSED) {
+                        if (offset & QCOW_OFLAG_COPIED) {
+                            printf("ERROR: cluster %lld: copied flag must never be set for compressed clusters\n",
+                                   offset >> s->cluster_bits);
+                            offset &= ~QCOW_OFLAG_COPIED;
+                        }
+                        nb_csectors = ((offset >> s->csize_shift) & 
+                                       s->csize_mask) + 1;
+                        offset &= s->cluster_offset_mask;
+                        inc_refcounts(bs, refcount_table, 
+                                      refcount_table_size,
+                                      offset & ~511, nb_csectors * 512);
+                    } else {
+                        if (check_copied) {
+                            refcount = get_refcount(bs, (offset & ~QCOW_OFLAG_COPIED) >> s->cluster_bits);
+                            if ((refcount == 1) != ((offset & QCOW_OFLAG_COPIED) != 0)) {
+                                printf("ERROR OFLAG_COPIED: offset=%llx refcount=%d\n",
+                                       offset, refcount);
+                            }
+                        }
+                        offset &= ~QCOW_OFLAG_COPIED;
+                        inc_refcounts(bs, refcount_table, 
+                                      refcount_table_size,
+                                      offset, s->cluster_size);
+                    }
+                }
+            }
+            inc_refcounts(bs, refcount_table, 
+                          refcount_table_size,
+                          l2_offset,
+                          s->cluster_size);
+        }
+    }
+    qemu_free(l1_table);
+    qemu_free(l2_table);
+    return 0;
+ fail:
+    printf("ERROR: I/O error in check_refcounts_l1\n");
+    qemu_free(l1_table);
+    qemu_free(l2_table);
+    return -EIO;
+}
+
+static void check_refcounts(BlockDriverState *bs)
+{
+    BDRVQcowState *s = bs->opaque;
+    int64_t size;
+    int nb_clusters, refcount1, refcount2, i;
+    QCowSnapshot *sn;
+    uint16_t *refcount_table;
+
+    size = bdrv_getlength(s->hd);
+    nb_clusters = (size + s->cluster_size - 1) >> s->cluster_bits;
+    refcount_table = qemu_mallocz(nb_clusters * sizeof(uint16_t));
+
+    /* header */
+    inc_refcounts(bs, refcount_table, nb_clusters,
+                  0, s->cluster_size);
+    
+    check_refcounts_l1(bs, refcount_table, nb_clusters,
+                       s->l1_table_offset, s->l1_size, 1);
+
+    /* snapshots */
+    for(i = 0; i < s->nb_snapshots; i++) {
+        sn = s->snapshots + i;
+        check_refcounts_l1(bs, refcount_table, nb_clusters,
+                           sn->l1_table_offset, sn->l1_size, 0);
+    }
+    inc_refcounts(bs, refcount_table, nb_clusters,
+                  s->snapshots_offset, s->snapshots_size);
+
+    /* refcount data */
+    inc_refcounts(bs, refcount_table, nb_clusters,
+                  s->refcount_table_offset, 
+                  s->refcount_table_size * sizeof(uint64_t));
+    for(i = 0; i < s->refcount_table_size; i++) {
+        int64_t offset;
+        offset = s->refcount_table[i];
+        if (offset != 0) {
+            inc_refcounts(bs, refcount_table, nb_clusters,
+                          offset, s->cluster_size);
+        }
+    }
+
+    /* compare ref counts */
+    for(i = 0; i < nb_clusters; i++) {
+        refcount1 = get_refcount(bs, i);
+        refcount2 = refcount_table[i];
+        if (refcount1 != refcount2)
+            printf("ERROR cluster %d refcount=%d reference=%d\n",
+                   i, refcount1, refcount2);
+    }
+
+    qemu_free(refcount_table);
+}
+
+#if 0
+static void dump_refcounts(BlockDriverState *bs)
+{
+    BDRVQcowState *s = bs->opaque;
+    int64_t nb_clusters, k, k1, size;
+    int refcount;
+
+    size = bdrv_getlength(s->hd);
+    nb_clusters = (size + s->cluster_size - 1) >> s->cluster_bits;
+    for(k = 0; k < nb_clusters;) {
+        k1 = k;
+        refcount = get_refcount(bs, k);
+        k++;
+        while (k < nb_clusters && get_refcount(bs, k) == refcount)
+            k++;
+        printf("%lld: refcount=%d nb=%lld\n", k, refcount, k - k1);
+    }
+}
+#endif
+#endif
+
+BlockDriver bdrv_qcow2 = {
+    "qcow2",
+    sizeof(BDRVQcowState),
+    qcow_probe,
+    qcow_open,
+    NULL,
+    NULL,
+    qcow_close,
+    qcow_create,
+    qcow_flush,
+    qcow_is_allocated,
+    qcow_set_key,
+    qcow_make_empty,
+
+    .bdrv_aio_read = qcow_aio_read,
+    .bdrv_aio_write = qcow_aio_write,
+    .bdrv_aio_cancel = qcow_aio_cancel,
+    .aiocb_size = sizeof(QCowAIOCB),
+    .bdrv_write_compressed = qcow_write_compressed,
+
+    .bdrv_snapshot_create = qcow_snapshot_create,
+    .bdrv_snapshot_goto = qcow_snapshot_goto,
+    .bdrv_snapshot_delete = qcow_snapshot_delete,
+    .bdrv_snapshot_list = qcow_snapshot_list,
+    .bdrv_get_info = qcow_get_info,
+};
diff --git a/tools/ioemu/block-raw.c b/tools/ioemu/block-raw.c
new file mode 100644 (file)
index 0000000..b1bdeed
--- /dev/null
@@ -0,0 +1,1353 @@
+/*
+ * Block driver for RAW files
+ * 
+ * Copyright (c) 2006 Fabrice Bellard
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+#include "block_int.h"
+#include <assert.h>
+#ifndef _WIN32
+#include <aio.h>
+
+#ifndef QEMU_TOOL
+#include "exec-all.h"
+#endif
+
+#ifdef CONFIG_COCOA
+#include <paths.h>
+#include <sys/param.h>
+#include <IOKit/IOKitLib.h>
+#include <IOKit/IOBSD.h>
+#include <IOKit/storage/IOMediaBSDClient.h>
+#include <IOKit/storage/IOMedia.h>
+#include <IOKit/storage/IOCDMedia.h>
+//#include <IOKit/storage/IOCDTypes.h>
+#include <CoreFoundation/CoreFoundation.h>
+#endif
+
+#ifdef __sun__
+#define _POSIX_PTHREAD_SEMANTICS 1
+#include <signal.h>
+#include <sys/dkio.h>
+#endif
+#ifdef __linux__
+#include <sys/ioctl.h>
+#include <linux/cdrom.h>
+#include <linux/fd.h>
+#endif
+#ifdef __FreeBSD__
+#include <sys/disk.h>
+#endif
+
+//#define DEBUG_FLOPPY
+
+#define FTYPE_FILE   0
+#define FTYPE_CD     1
+#define FTYPE_FD     2
+
+/* if the FD is not accessed during that time (in ms), we try to
+   reopen it to see if the disk has been changed */
+#define FD_OPEN_TIMEOUT 1000
+
+typedef struct BDRVRawState {
+    int fd;
+    int type;
+#if defined(__linux__)
+    /* linux floppy specific */
+    int fd_open_flags;
+    int64_t fd_open_time;
+    int64_t fd_error_time;
+    int fd_got_error;
+    int fd_media_changed;
+#endif
+} BDRVRawState;
+
+static int fd_open(BlockDriverState *bs);
+
+static int raw_open(BlockDriverState *bs, const char *filename, int flags)
+{
+    BDRVRawState *s = bs->opaque;
+    int fd, open_flags, ret;
+
+    open_flags = O_BINARY;
+    if ((flags & BDRV_O_ACCESS) == O_RDWR) {
+        open_flags |= O_RDWR;
+    } else {
+        open_flags |= O_RDONLY;
+        bs->read_only = 1;
+    }
+    if (flags & BDRV_O_CREAT)
+        open_flags |= O_CREAT | O_TRUNC;
+
+    s->type = FTYPE_FILE;
+
+    fd = open(filename, open_flags, 0644);
+    if (fd < 0) {
+        ret = -errno;
+        if (ret == -EROFS)
+            ret = -EACCES;
+        return ret;
+    }
+    s->fd = fd;
+    return 0;
+}
+
+/* XXX: use host sector size if necessary with:
+#ifdef DIOCGSECTORSIZE
+        {
+            unsigned int sectorsize = 512;
+            if (!ioctl(fd, DIOCGSECTORSIZE, &sectorsize) &&
+                sectorsize > bufsize)
+                bufsize = sectorsize;
+        }
+#endif
+#ifdef CONFIG_COCOA
+        u_int32_t   blockSize = 512;
+        if ( !ioctl( fd, DKIOCGETBLOCKSIZE, &blockSize ) && blockSize > bufsize) {
+            bufsize = blockSize;
+        }
+#endif
+*/
+
+static int raw_pread(BlockDriverState *bs, int64_t offset, 
+                     uint8_t *buf, int count)
+{
+    BDRVRawState *s = bs->opaque;
+    int ret;
+    
+    ret = fd_open(bs);
+    if (ret < 0)
+        return ret;
+
+    lseek(s->fd, offset, SEEK_SET);
+    ret = read(s->fd, buf, count);
+    return ret;
+}
+
+static int raw_pwrite(BlockDriverState *bs, int64_t offset, 
+                      const uint8_t *buf, int count)
+{
+    BDRVRawState *s = bs->opaque;
+    int ret;
+    
+    ret = fd_open(bs);
+    if (ret < 0)
+        return ret;
+
+    lseek(s->fd, offset, SEEK_SET);
+    ret = write(s->fd, buf, count);
+    return ret;
+}
+
+/***********************************************************/
+/* Unix AIO using POSIX AIO */
+
+typedef struct RawAIOCB {
+    BlockDriverAIOCB common;
+    struct aiocb aiocb;
+    struct RawAIOCB *next;
+} RawAIOCB;
+
+static int aio_sig_num = SIGUSR2;
+static RawAIOCB *first_aio; /* AIO issued */
+static int aio_initialized = 0;
+
+static void aio_signal_handler(int signum)
+{
+#ifndef QEMU_TOOL
+    CPUState *env = cpu_single_env;
+    if (env) {
+        /* stop the currently executing cpu because a timer occured */
+        cpu_interrupt(env, CPU_INTERRUPT_EXIT);
+#ifdef USE_KQEMU
+        if (env->kqemu_enabled) {
+            kqemu_cpu_interrupt(env);
+        }
+#endif
+    }
+#endif
+}
+
+void qemu_aio_init(void)
+{
+    struct sigaction act;
+
+    aio_initialized = 1;
+    
+    sigfillset(&act.sa_mask);
+    act.sa_flags = 0; /* do not restart syscalls to interrupt select() */
+    act.sa_handler = aio_signal_handler;
+    sigaction(aio_sig_num, &act, NULL);
+
+#if defined(__GLIBC__) && defined(__linux__)
+    {
+        /* XXX: aio thread exit seems to hang on RedHat 9 and this init
+           seems to fix the problem. */
+        struct aioinit ai;
+        memset(&ai, 0, sizeof(ai));
+        ai.aio_threads = 1;
+        ai.aio_num = 1;
+        ai.aio_idle_time = 365 * 100000;
+        aio_init(&ai);
+    }
+#endif
+}
+
+void qemu_aio_poll(void)
+{
+    RawAIOCB *acb, **pacb;
+    int ret;
+
+    for(;;) {
+        pacb = &first_aio;
+        for(;;) {
+            acb = *pacb;
+            if (!acb)
+                goto the_end;
+            ret = aio_error(&acb->aiocb);
+            if (ret == ECANCELED) {
+                /* remove the request */
+                *pacb = acb->next;
+                qemu_aio_release(acb);
+            } else if (ret != EINPROGRESS) {
+                /* end of aio */
+                if (ret == 0) {
+                    ret = aio_return(&acb->aiocb);
+                    if (ret == acb->aiocb.aio_nbytes)
+                        ret = 0;
+                    else
+                        ret = -EINVAL;
+                } else {
+                    ret = -ret;
+                }
+                /* remove the request */
+                *pacb = acb->next;
+                /* call the callback */
+                acb->common.cb(acb->common.opaque, ret);
+                qemu_aio_release(acb);
+                break;
+            } else {
+                pacb = &acb->next;
+            }
+        }
+    }
+ the_end: ;
+}
+
+/* Wait for all IO requests to complete.  */
+void qemu_aio_flush(void)
+{
+    qemu_aio_wait_start();
+    qemu_aio_poll();
+    while (first_aio) {
+        qemu_aio_wait();
+    }
+    qemu_aio_wait_end();
+}
+
+/* wait until at least one AIO was handled */
+static sigset_t wait_oset;
+
+void qemu_aio_wait_start(void)
+{
+    sigset_t set;
+
+    if (!aio_initialized)
+        qemu_aio_init();
+    sigemptyset(&set);
+    sigaddset(&set, aio_sig_num);
+    sigprocmask(SIG_BLOCK, &set, &wait_oset);
+}
+
+void qemu_aio_wait(void)
+{
+    sigset_t set;
+    int nb_sigs;
+
+#ifndef QEMU_TOOL
+    if (qemu_bh_poll())
+        return;
+#endif
+    sigemptyset(&set);
+    sigaddset(&set, aio_sig_num);
+    sigwait(&set, &nb_sigs);
+    qemu_aio_poll();
+}
+
+void qemu_aio_wait_end(void)
+{
+    sigprocmask(SIG_SETMASK, &wait_oset, NULL);
+}
+
+static RawAIOCB *raw_aio_setup(BlockDriverState *bs,
+        int64_t sector_num, uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque)
+{
+    BDRVRawState *s = bs->opaque;
+    RawAIOCB *acb;
+
+    if (fd_open(bs) < 0)
+        return NULL;
+
+    acb = qemu_aio_get(bs, cb, opaque);
+    if (!acb)
+        return NULL;
+    acb->aiocb.aio_fildes = s->fd;
+    acb->aiocb.aio_sigevent.sigev_signo = aio_sig_num;
+    acb->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
+    acb->aiocb.aio_buf = buf;
+    acb->aiocb.aio_nbytes = nb_sectors * 512;
+    acb->aiocb.aio_offset = sector_num * 512;
+    acb->next = first_aio;
+    first_aio = acb;
+    return acb;
+}
+
+static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs,
+        int64_t sector_num, uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque)
+{
+    RawAIOCB *acb;
+
+    acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
+    if (!acb)
+        return NULL;
+    if (aio_read(&acb->aiocb) < 0) {
+        qemu_aio_release(acb);
+        return NULL;
+    } 
+    return &acb->common;
+}
+
+static BlockDriverAIOCB *raw_aio_write(BlockDriverState *bs,
+        int64_t sector_num, const uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque)
+{
+    RawAIOCB *acb;
+
+    acb = raw_aio_setup(bs, sector_num, (uint8_t*)buf, nb_sectors, cb, opaque);
+    if (!acb)
+        return NULL;
+    if (aio_write(&acb->aiocb) < 0) {
+        qemu_aio_release(acb);
+        return NULL;
+    } 
+    return &acb->common;
+}
+
+static void raw_aio_cancel(BlockDriverAIOCB *blockacb)
+{
+    int ret;
+    RawAIOCB *acb = (RawAIOCB *)blockacb;
+    RawAIOCB **pacb;
+
+    ret = aio_cancel(acb->aiocb.aio_fildes, &acb->aiocb);
+    if (ret == AIO_NOTCANCELED) {
+        /* fail safe: if the aio could not be canceled, we wait for
+           it */
+        while (aio_error(&acb->aiocb) == EINPROGRESS);
+    }
+
+    /* remove the callback from the queue */
+    pacb = &first_aio;
+    for(;;) {
+        if (*pacb == NULL) {
+            break;
+        } else if (*pacb == acb) {
+            *pacb = acb->next;
+            qemu_aio_release(acb);
+            break;
+        }
+        pacb = &acb->next;
+    }
+}
+
+static void raw_close(BlockDriverState *bs)
+{
+    BDRVRawState *s = bs->opaque;
+    bs->total_sectors = 0;
+    if (s->fd >= 0) {
+        close(s->fd);
+        s->fd = -1;
+    }
+}
+
+static int raw_truncate(BlockDriverState *bs, int64_t offset)
+{
+    BDRVRawState *s = bs->opaque;
+    if (s->type != FTYPE_FILE)
+        return -ENOTSUP;
+    if (ftruncate(s->fd, offset) < 0)
+        return -errno;
+    return 0;
+}
+
+static int64_t  raw_getlength(BlockDriverState *bs)
+{
+    BDRVRawState *s = bs->opaque;
+    int fd = s->fd;
+    int64_t size;
+#ifdef _BSD
+    struct stat sb;
+#endif
+#ifdef __sun__
+    struct dk_minfo minfo;
+    int rv;
+#endif
+    int ret;
+
+    ret = fd_open(bs);
+    if (ret < 0)
+        return ret;
+
+#ifdef _BSD
+    if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) {
+#ifdef DIOCGMEDIASIZE
+       if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size))
+#endif
+#ifdef CONFIG_COCOA
+        size = LONG_LONG_MAX;
+#else
+        size = lseek(fd, 0LL, SEEK_END);
+#endif
+    } else
+#endif
+#ifdef __sun__
+    /*
+     * use the DKIOCGMEDIAINFO ioctl to read the size.
+     */
+    rv = ioctl ( fd, DKIOCGMEDIAINFO, &minfo );
+    if ( rv != -1 ) {
+        size = minfo.dki_lbsize * minfo.dki_capacity;
+    } else /* there are reports that lseek on some devices
+              fails, but irc discussion said that contingency
+              on contingency was overkill */
+#endif
+    {
+        size = lseek(fd, 0, SEEK_END);
+    }
+    return size;
+}
+
+static int raw_create(const char *filename, int64_t total_size,
+                      const char *backing_file, int flags)
+{
+    int fd;
+
+    if (flags || backing_file)
+        return -ENOTSUP;
+
+    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 
+              0644);
+    if (fd < 0)
+        return -EIO;
+    ftruncate(fd, total_size * 512);
+    close(fd);
+    return 0;
+}
+
+static void raw_flush(BlockDriverState *bs)
+{
+    BDRVRawState *s = bs->opaque;
+    fsync(s->fd);
+}
+
+BlockDriver bdrv_raw = {
+    "raw",
+    sizeof(BDRVRawState),
+    NULL, /* no probe for protocols */
+    raw_open,
+    NULL,
+    NULL,
+    raw_close,
+    raw_create,
+    raw_flush,
+    
+    .bdrv_aio_read = raw_aio_read,
+    .bdrv_aio_write = raw_aio_write,
+    .bdrv_aio_cancel = raw_aio_cancel,
+    .aiocb_size = sizeof(RawAIOCB),
+    .protocol_name = "file",
+    .bdrv_pread = raw_pread,
+    .bdrv_pwrite = raw_pwrite,
+    .bdrv_truncate = raw_truncate,
+    .bdrv_getlength = raw_getlength,
+};
+
+/***********************************************/
+/* host device */
+
+#ifdef CONFIG_COCOA
+static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator );
+static kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize );
+
+kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator )
+{
+    kern_return_t       kernResult; 
+    mach_port_t     masterPort;
+    CFMutableDictionaryRef  classesToMatch;
+
+    kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort );
+    if ( KERN_SUCCESS != kernResult ) {
+        printf( "IOMasterPort returned %d\n", kernResult );
+    }
+    
+    classesToMatch = IOServiceMatching( kIOCDMediaClass ); 
+    if ( classesToMatch == NULL ) {
+        printf( "IOServiceMatching returned a NULL dictionary.\n" );
+    } else {
+    CFDictionarySetValue( classesToMatch, CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue );
+    }
+    kernResult = IOServiceGetMatchingServices( masterPort, classesToMatch, mediaIterator );
+    if ( KERN_SUCCESS != kernResult )
+    {
+        printf( "IOServiceGetMatchingServices returned %d\n", kernResult );
+    }
+    
+    return kernResult;
+}
+
+kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize )
+{
+    io_object_t     nextMedia;
+    kern_return_t   kernResult = KERN_FAILURE;
+    *bsdPath = '\0';
+    nextMedia = IOIteratorNext( mediaIterator );
+    if ( nextMedia )
+    {
+        CFTypeRef   bsdPathAsCFString;
+    bsdPathAsCFString = IORegistryEntryCreateCFProperty( nextMedia, CFSTR( kIOBSDNameKey ), kCFAllocatorDefault, 0 );
+        if ( bsdPathAsCFString ) {
+            size_t devPathLength;
+            strcpy( bsdPath, _PATH_DEV );
+            strcat( bsdPath, "r" );
+            devPathLength = strlen( bsdPath );
+            if ( CFStringGetCString( bsdPathAsCFString, bsdPath + devPathLength, maxPathSize - devPathLength, kCFStringEncodingASCII ) ) {
+                kernResult = KERN_SUCCESS;
+            }
+            CFRelease( bsdPathAsCFString );
+        }
+        IOObjectRelease( nextMedia );
+    }
+    
+    return kernResult;
+}
+
+#endif
+
+static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
+{
+    BDRVRawState *s = bs->opaque;
+    int fd, open_flags, ret;
+
+#ifdef CONFIG_COCOA
+    if (strstart(filename, "/dev/cdrom", NULL)) {
+        kern_return_t kernResult;
+        io_iterator_t mediaIterator;
+        char bsdPath[ MAXPATHLEN ];
+        int fd;
+        kernResult = FindEjectableCDMedia( &mediaIterator );
+        kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof( bsdPath ) );
+    
+        if ( bsdPath[ 0 ] != '\0' ) {
+            strcat(bsdPath,"s0");
+            /* some CDs don't have a partition 0 */
+            fd = open(bsdPath, O_RDONLY | O_BINARY | O_LARGEFILE);
+            if (fd < 0) {
+                bsdPath[strlen(bsdPath)-1] = '1';
+            } else {
+                close(fd);
+            }
+            filename = bsdPath;
+        }
+        
+        if ( mediaIterator )
+            IOObjectRelease( mediaIterator );
+    }
+#endif
+    open_flags = O_BINARY;
+    if ((flags & BDRV_O_ACCESS) == O_RDWR) {
+        open_flags |= O_RDWR;
+    } else {
+        open_flags |= O_RDONLY;
+        bs->read_only = 1;
+    }
+
+    s->type = FTYPE_FILE;
+#if defined(__linux__)
+    if (strstart(filename, "/dev/cd", NULL)) {
+        /* open will not fail even if no CD is inserted */
+        open_flags |= O_NONBLOCK;
+        s->type = FTYPE_CD;
+    } else if (strstart(filename, "/dev/fd", NULL)) {
+        s->type = FTYPE_FD;
+        s->fd_open_flags = open_flags;
+        /* open will not fail even if no floppy is inserted */
+        open_flags |= O_NONBLOCK;
+    }
+#endif
+    fd = open(filename, open_flags, 0644);
+    if (fd < 0) {
+        ret = -errno;
+        if (ret == -EROFS)
+            ret = -EACCES;
+        return ret;
+    }
+    s->fd = fd;
+#if defined(__linux__)
+    /* close fd so that we can reopen it as needed */
+    if (s->type == FTYPE_FD) {
+        close(s->fd);
+        s->fd = -1;
+        s->fd_media_changed = 1;
+    }
+#endif
+    return 0;
+}
+
+#if defined(__linux__) && !defined(QEMU_TOOL)
+
+/* Note: we do not have a reliable method to detect if the floppy is
+   present. The current method is to try to open the floppy at every
+   I/O and to keep it opened during a few hundreds of ms. */
+static int fd_open(BlockDriverState *bs)
+{
+    BDRVRawState *s = bs->opaque;
+    int last_media_present;
+
+    if (s->type != FTYPE_FD)
+        return 0;
+    last_media_present = (s->fd >= 0);
+    if (s->fd >= 0 && 
+        (qemu_get_clock(rt_clock) - s->fd_open_time) >= FD_OPEN_TIMEOUT) {
+        close(s->fd);
+        s->fd = -1;
+#ifdef DEBUG_FLOPPY
+        printf("Floppy closed\n");
+#endif
+    }
+    if (s->fd < 0) {
+        if (s->fd_got_error && 
+            (qemu_get_clock(rt_clock) - s->fd_error_time) < FD_OPEN_TIMEOUT) {
+#ifdef DEBUG_FLOPPY
+            printf("No floppy (open delayed)\n");
+#endif
+            return -EIO;
+        }
+        s->fd = open(bs->filename, s->fd_open_flags);
+        if (s->fd < 0) {
+            s->fd_error_time = qemu_get_clock(rt_clock);
+            s->fd_got_error = 1;
+            if (last_media_present)
+                s->fd_media_changed = 1;
+#ifdef DEBUG_FLOPPY
+            printf("No floppy\n");
+#endif
+            return -EIO;
+        }
+#ifdef DEBUG_FLOPPY
+        printf("Floppy opened\n");
+#endif
+    }
+    if (!last_media_present)
+        s->fd_media_changed = 1;
+    s->fd_open_time = qemu_get_clock(rt_clock);
+    s->fd_got_error = 0;
+    return 0;
+}
+#else
+static int fd_open(BlockDriverState *bs)
+{
+    return 0;
+}
+#endif
+
+#if defined(__linux__)
+
+static int raw_is_inserted(BlockDriverState *bs)
+{
+    BDRVRawState *s = bs->opaque;
+    int ret;
+
+    switch(s->type) {
+    case FTYPE_CD:
+        ret = ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
+        if (ret == CDS_DISC_OK)
+            return 1;
+        else
+            return 0;
+        break;
+    case FTYPE_FD:
+        ret = fd_open(bs);
+        return (ret >= 0);
+    default:
+        return 1;
+    }
+}
+
+/* currently only used by fdc.c, but a CD version would be good too */
+static int raw_media_changed(BlockDriverState *bs)
+{
+    BDRVRawState *s = bs->opaque;
+
+    switch(s->type) {
+    case FTYPE_FD:
+        {
+            int ret;
+            /* XXX: we do not have a true media changed indication. It
+               does not work if the floppy is changed without trying
+               to read it */
+            fd_open(bs);
+            ret = s->fd_media_changed;
+            s->fd_media_changed = 0;
+#ifdef DEBUG_FLOPPY
+            printf("Floppy changed=%d\n", ret);
+#endif
+            return ret;
+        }
+    default:
+        return -ENOTSUP;
+    }
+}
+
+static int raw_eject(BlockDriverState *bs, int eject_flag)
+{
+    BDRVRawState *s = bs->opaque;
+
+    switch(s->type) {
+    case FTYPE_CD:
+        if (eject_flag) {
+            if (ioctl (s->fd, CDROMEJECT, NULL) < 0)
+                perror("CDROMEJECT");
+        } else {
+            if (ioctl (s->fd, CDROMCLOSETRAY, NULL) < 0)
+                perror("CDROMEJECT");
+        }
+        break;
+    case FTYPE_FD:
+        {
+            int fd;
+            if (s->fd >= 0) {
+                close(s->fd);
+                s->fd = -1;
+            }
+            fd = open(bs->filename, s->fd_open_flags | O_NONBLOCK);
+            if (fd >= 0) {
+                if (ioctl(fd, FDEJECT, 0) < 0)
+                    perror("FDEJECT");
+                close(fd);
+            }
+        }
+        break;
+    default:
+        return -ENOTSUP;
+    }
+    return 0;
+}
+
+static int raw_set_locked(BlockDriverState *bs, int locked)
+{
+    BDRVRawState *s = bs->opaque;
+
+    switch(s->type) {
+    case FTYPE_CD:
+        if (ioctl (s->fd, CDROM_LOCKDOOR, locked) < 0) {
+            /* Note: an error can happen if the distribution automatically
+               mounts the CD-ROM */
+            //        perror("CDROM_LOCKDOOR");
+        }
+        break;
+    default:
+        return -ENOTSUP;
+    }
+    return 0;
+}
+
+#else
+
+static int raw_is_inserted(BlockDriverState *bs)
+{
+    return 1;
+}
+
+static int raw_media_changed(BlockDriverState *bs)
+{
+    return -ENOTSUP;
+}
+
+static int raw_eject(BlockDriverState *bs, int eject_flag)
+{
+    return -ENOTSUP;
+}
+
+static int raw_set_locked(BlockDriverState *bs, int locked)
+{
+    return -ENOTSUP;
+}
+
+#endif /* !linux */
+
+BlockDriver bdrv_host_device = {
+    "host_device",
+    sizeof(BDRVRawState),
+    NULL, /* no probe for protocols */
+    hdev_open,
+    NULL,
+    NULL,
+    raw_close,
+    NULL,
+    raw_flush,
+    
+    .bdrv_aio_read = raw_aio_read,
+    .bdrv_aio_write = raw_aio_write,
+    .bdrv_aio_cancel = raw_aio_cancel,
+    .aiocb_size = sizeof(RawAIOCB),
+    .bdrv_pread = raw_pread,
+    .bdrv_pwrite = raw_pwrite,
+    .bdrv_getlength = raw_getlength,
+
+    /* removable device support */
+    .bdrv_is_inserted = raw_is_inserted,
+    .bdrv_media_changed = raw_media_changed,
+    .bdrv_eject = raw_eject,
+    .bdrv_set_locked = raw_set_locked,
+};
+
+#else /* _WIN32 */
+
+/* XXX: use another file ? */
+#include <winioctl.h>
+
+#define FTYPE_FILE 0
+#define FTYPE_CD     1
+#define FTYPE_HARDDISK 2
+
+typedef struct BDRVRawState {
+    HANDLE hfile;
+    int type;
+    char drive_path[16]; /* format: "d:\" */
+} BDRVRawState;
+
+typedef struct RawAIOCB {
+    BlockDriverAIOCB common;
+    HANDLE hEvent;
+    OVERLAPPED ov;
+    int count;
+} RawAIOCB;
+
+int qemu_ftruncate64(int fd, int64_t length)
+{
+    LARGE_INTEGER li;
+    LONG high;
+    HANDLE h;
+    BOOL res;
+
+    if ((GetVersion() & 0x80000000UL) && (length >> 32) != 0)
+       return -1;
+
+    h = (HANDLE)_get_osfhandle(fd);
+
+    /* get current position, ftruncate do not change position */
+    li.HighPart = 0;
+    li.LowPart = SetFilePointer (h, 0, &li.HighPart, FILE_CURRENT);
+    if (li.LowPart == 0xffffffffUL && GetLastError() != NO_ERROR)
+       return -1;
+
+    high = length >> 32;
+    if (!SetFilePointer(h, (DWORD) length, &high, FILE_BEGIN))
+       return -1;
+    res = SetEndOfFile(h);
+
+    /* back to old position */
+    SetFilePointer(h, li.LowPart, &li.HighPart, FILE_BEGIN);
+    return res ? 0 : -1;
+}
+
+static int set_sparse(int fd)
+{
+    DWORD returned;
+    return (int) DeviceIoControl((HANDLE)_get_osfhandle(fd), FSCTL_SET_SPARSE,
+                                NULL, 0, NULL, 0, &returned, NULL);
+}
+
+static int raw_open(BlockDriverState *bs, const char *filename, int flags)
+{
+    BDRVRawState *s = bs->opaque;
+    int access_flags, create_flags;
+    DWORD overlapped;
+
+    s->type = FTYPE_FILE;
+
+    if ((flags & BDRV_O_ACCESS) == O_RDWR) {
+        access_flags = GENERIC_READ | GENERIC_WRITE;
+    } else {
+        access_flags = GENERIC_READ;
+    }
+    if (flags & BDRV_O_CREAT) {
+        create_flags = CREATE_ALWAYS;
+    } else {
+        create_flags = OPEN_EXISTING;
+    }
+#ifdef QEMU_TOOL
+    overlapped = FILE_ATTRIBUTE_NORMAL;
+#else
+    overlapped = FILE_FLAG_OVERLAPPED;
+#endif
+    s->hfile = CreateFile(filename, access_flags, 
+                          FILE_SHARE_READ, NULL,
+                          create_flags, overlapped, NULL);
+    if (s->hfile == INVALID_HANDLE_VALUE) {
+        int err = GetLastError();
+
+        if (err == ERROR_ACCESS_DENIED)
+            return -EACCES;
+        return -1;
+    }
+    return 0;
+}
+
+static int raw_pread(BlockDriverState *bs, int64_t offset, 
+                     uint8_t *buf, int count)
+{
+    BDRVRawState *s = bs->opaque;
+    OVERLAPPED ov;
+    DWORD ret_count;
+    int ret;
+    
+    memset(&ov, 0, sizeof(ov));
+    ov.Offset = offset;
+    ov.OffsetHigh = offset >> 32;
+    ret = ReadFile(s->hfile, buf, count, &ret_count, &ov);
+    if (!ret) {
+        ret = GetOverlappedResult(s->hfile, &ov, &ret_count, TRUE);
+        if (!ret)
+            return -EIO;
+        else
+            return ret_count;
+    }
+    return ret_count;
+}
+
+static int raw_pwrite(BlockDriverState *bs, int64_t offset, 
+                      const uint8_t *buf, int count)
+{
+    BDRVRawState *s = bs->opaque;
+    OVERLAPPED ov;
+    DWORD ret_count;
+    int ret;
+    
+    memset(&ov, 0, sizeof(ov));
+    ov.Offset = offset;
+    ov.OffsetHigh = offset >> 32;
+    ret = WriteFile(s->hfile, buf, count, &ret_count, &ov);
+    if (!ret) {
+        ret = GetOverlappedResult(s->hfile, &ov, &ret_count, TRUE);
+        if (!ret)
+            return -EIO;
+        else
+            return ret_count;
+    }
+    return ret_count;
+}
+
+#if 0
+#ifndef QEMU_TOOL
+static void raw_aio_cb(void *opaque)
+{
+    RawAIOCB *acb = opaque;
+    BlockDriverState *bs = acb->common.bs;
+    BDRVRawState *s = bs->opaque;
+    DWORD ret_count;
+    int ret;
+
+    ret = GetOverlappedResult(s->hfile, &acb->ov, &ret_count, TRUE);
+    if (!ret || ret_count != acb->count) {
+        acb->common.cb(acb->common.opaque, -EIO);
+    } else {
+        acb->common.cb(acb->common.opaque, 0);
+    }
+}
+#endif
+
+static RawAIOCB *raw_aio_setup(BlockDriverState *bs,
+        int64_t sector_num, uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque)
+{
+    RawAIOCB *acb;
+    int64_t offset;
+
+    acb = qemu_aio_get(bs, cb, opaque);
+    if (acb->hEvent) {
+        acb->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+        if (!acb->hEvent) {
+            qemu_aio_release(acb);
+            return NULL;
+        }
+    }
+    memset(&acb->ov, 0, sizeof(acb->ov));
+    offset = sector_num * 512;
+    acb->ov.Offset = offset;
+    acb->ov.OffsetHigh = offset >> 32;
+    acb->ov.hEvent = acb->hEvent;
+    acb->count = nb_sectors * 512;
+#ifndef QEMU_TOOL
+    qemu_add_wait_object(acb->ov.hEvent, raw_aio_cb, acb);
+#endif
+    return acb;
+}
+
+static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs,
+        int64_t sector_num, uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque)
+{
+    BDRVRawState *s = bs->opaque;
+    RawAIOCB *acb;
+    int ret;
+
+    acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
+    if (!acb)
+        return NULL;
+    ret = ReadFile(s->hfile, buf, acb->count, NULL, &acb->ov);
+    if (!ret) {
+        qemu_aio_release(acb);
+        return NULL;
+    }
+#ifdef QEMU_TOOL
+    qemu_aio_release(acb);
+#endif
+    return (BlockDriverAIOCB *)acb;
+}
+
+static BlockDriverAIOCB *raw_aio_write(BlockDriverState *bs,
+        int64_t sector_num, uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque)
+{
+    BDRVRawState *s = bs->opaque;
+    RawAIOCB *acb;
+    int ret;
+
+    acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
+    if (!acb)
+        return NULL;
+    ret = WriteFile(s->hfile, buf, acb->count, NULL, &acb->ov);
+    if (!ret) {
+        qemu_aio_release(acb);
+        return NULL;
+    }
+#ifdef QEMU_TOOL
+    qemu_aio_release(acb);
+#endif
+    return (BlockDriverAIOCB *)acb;
+}
+
+static void raw_aio_cancel(BlockDriverAIOCB *blockacb)
+{
+#ifndef QEMU_TOOL
+    RawAIOCB *acb = (RawAIOCB *)blockacb;
+    BlockDriverState *bs = acb->common.bs;
+    BDRVRawState *s = bs->opaque;
+
+    qemu_del_wait_object(acb->ov.hEvent, raw_aio_cb, acb);
+    /* XXX: if more than one async I/O it is not correct */
+    CancelIo(s->hfile);
+    qemu_aio_release(acb);
+#endif
+}
+#endif /* #if 0 */
+
+static void raw_flush(BlockDriverState *bs)
+{
+    BDRVRawState *s = bs->opaque;
+    FlushFileBuffers(s->hfile);
+}
+
+static void raw_close(BlockDriverState *bs)
+{
+    BDRVRawState *s = bs->opaque;
+    CloseHandle(s->hfile);
+}
+
+static int raw_truncate(BlockDriverState *bs, int64_t offset)
+{
+    BDRVRawState *s = bs->opaque;
+    DWORD low, high;
+
+    low = offset;
+    high = offset >> 32;
+    if (!SetFilePointer(s->hfile, low, &high, FILE_BEGIN))
+       return -EIO;
+    if (!SetEndOfFile(s->hfile))
+        return -EIO;
+    return 0;
+}
+
+static int64_t raw_getlength(BlockDriverState *bs)
+{
+    BDRVRawState *s = bs->opaque;
+    LARGE_INTEGER l;
+    ULARGE_INTEGER available, total, total_free; 
+    DISK_GEOMETRY dg;
+    DWORD count;
+    BOOL status;
+
+    switch(s->type) {
+    case FTYPE_FILE:
+        l.LowPart = GetFileSize(s->hfile, &l.HighPart);
+        if (l.LowPart == 0xffffffffUL && GetLastError() != NO_ERROR)
+            return -EIO;
+        break;
+    case FTYPE_CD:
+        if (!GetDiskFreeSpaceEx(s->drive_path, &available, &total, &total_free))
+            return -EIO;
+        l.QuadPart = total.QuadPart;
+        break;
+    case FTYPE_HARDDISK:
+        status = DeviceIoControl(s->hfile, IOCTL_DISK_GET_DRIVE_GEOMETRY,
+                                 NULL, 0, &dg, sizeof(dg), &count, NULL);
+        if (status != FALSE) {
+            l.QuadPart = dg.Cylinders.QuadPart * dg.TracksPerCylinder
+                * dg.SectorsPerTrack * dg.BytesPerSector;
+        }
+        break;
+    default:
+        return -EIO;
+    }
+    return l.QuadPart;
+}
+
+static int raw_create(const char *filename, int64_t total_size,
+                      const char *backing_file, int flags)
+{
+    int fd;
+
+    if (flags || backing_file)
+        return -ENOTSUP;
+
+    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 
+              0644);
+    if (fd < 0)
+        return -EIO;
+    set_sparse(fd);
+    ftruncate(fd, total_size * 512);
+    close(fd);
+    return 0;
+}
+
+void qemu_aio_init(void)
+{
+}
+
+void qemu_aio_poll(void)
+{
+}
+
+void qemu_aio_flush(void)
+{
+}
+
+void qemu_aio_wait_start(void)
+{
+}
+
+void qemu_aio_wait(void)
+{
+#ifndef QEMU_TOOL
+    qemu_bh_poll();
+#endif
+}
+
+void qemu_aio_wait_end(void)
+{
+}
+
+BlockDriver bdrv_raw = {
+    "raw",
+    sizeof(BDRVRawState),
+    NULL, /* no probe for protocols */
+    raw_open,
+    NULL,
+    NULL,
+    raw_close,
+    raw_create,
+    raw_flush,
+    
+#if 0
+    .bdrv_aio_read = raw_aio_read,
+    .bdrv_aio_write = raw_aio_write,
+    .bdrv_aio_cancel = raw_aio_cancel,
+    .aiocb_size = sizeof(RawAIOCB);
+#endif
+    .protocol_name = "file",
+    .bdrv_pread = raw_pread,
+    .bdrv_pwrite = raw_pwrite,
+    .bdrv_truncate = raw_truncate,
+    .bdrv_getlength = raw_getlength,
+};
+
+/***********************************************/
+/* host device */
+
+static int find_cdrom(char *cdrom_name, int cdrom_name_size)
+{
+    char drives[256], *pdrv = drives;
+    UINT type;
+
+    memset(drives, 0, sizeof(drives));
+    GetLogicalDriveStrings(sizeof(drives), drives);
+    while(pdrv[0] != '\0') {
+        type = GetDriveType(pdrv);
+        switch(type) {
+        case DRIVE_CDROM:
+            snprintf(cdrom_name, cdrom_name_size, "\\\\.\\%c:", pdrv[0]);
+            return 0;
+            break;
+        }
+        pdrv += lstrlen(pdrv) + 1;
+    }
+    return -1;
+}
+
+static int find_device_type(BlockDriverState *bs, const char *filename)
+{
+    BDRVRawState *s = bs->opaque;
+    UINT type;
+    const char *p;
+
+    if (strstart(filename, "\\\\.\\", &p) ||
+        strstart(filename, "//./", &p)) {
+        if (stristart(p, "PhysicalDrive", NULL))
+            return FTYPE_HARDDISK;
+        snprintf(s->drive_path, sizeof(s->drive_path), "%c:\\", p[0]);
+        type = GetDriveType(s->drive_path);
+        if (type == DRIVE_CDROM)
+            return FTYPE_CD;
+        else
+            return FTYPE_FILE;
+    } else {
+        return FTYPE_FILE;
+    }
+}
+
+static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
+{
+    BDRVRawState *s = bs->opaque;
+    int access_flags, create_flags;
+    DWORD overlapped;
+    char device_name[64];
+
+    if (strstart(filename, "/dev/cdrom", NULL)) {
+        if (find_cdrom(device_name, sizeof(device_name)) < 0)
+            return -ENOENT;
+        filename = device_name;
+    } else {
+        /* transform drive letters into device name */
+        if (((filename[0] >= 'a' && filename[0] <= 'z') ||
+             (filename[0] >= 'A' && filename[0] <= 'Z')) &&
+            filename[1] == ':' && filename[2] == '\0') {
+            snprintf(device_name, sizeof(device_name), "\\\\.\\%c:", filename[0]);
+            filename = device_name;
+        }
+    }
+    s->type = find_device_type(bs, filename);
+    
+    if ((flags & BDRV_O_ACCESS) == O_RDWR) {
+        access_flags = GENERIC_READ | GENERIC_WRITE;
+    } else {
+        access_flags = GENERIC_READ;
+    }
+    create_flags = OPEN_EXISTING;
+
+#ifdef QEMU_TOOL
+    overlapped = FILE_ATTRIBUTE_NORMAL;
+#else
+    overlapped = FILE_FLAG_OVERLAPPED;
+#endif
+    s->hfile = CreateFile(filename, access_flags, 
+                          FILE_SHARE_READ, NULL,
+                          create_flags, overlapped, NULL);
+    if (s->hfile == INVALID_HANDLE_VALUE) {
+        int err = GetLastError();
+
+        if (err == ERROR_ACCESS_DENIED)
+            return -EACCES;
+        return -1;
+    }
+    return 0;
+}
+
+#if 0
+/***********************************************/
+/* removable device additionnal commands */
+
+static int raw_is_inserted(BlockDriverState *bs)
+{
+    return 1;
+}
+
+static int raw_media_changed(BlockDriverState *bs)
+{
+    return -ENOTSUP;
+}
+
+static int raw_eject(BlockDriverState *bs, int eject_flag)
+{
+    DWORD ret_count;
+
+    if (s->type == FTYPE_FILE)
+        return -ENOTSUP;
+    if (eject_flag) {
+        DeviceIoControl(s->hfile, IOCTL_STORAGE_EJECT_MEDIA, 
+                        NULL, 0, NULL, 0, &lpBytesReturned, NULL);
+    } else {
+        DeviceIoControl(s->hfile, IOCTL_STORAGE_LOAD_MEDIA, 
+                        NULL, 0, NULL, 0, &lpBytesReturned, NULL);
+    }
+}
+
+static int raw_set_locked(BlockDriverState *bs, int locked)
+{
+    return -ENOTSUP;
+}
+#endif
+
+BlockDriver bdrv_host_device = {
+    "host_device",
+    sizeof(BDRVRawState),
+    NULL, /* no probe for protocols */
+    hdev_open,
+    NULL,
+    NULL,
+    raw_close,
+    NULL,
+    raw_flush,
+    
+#if 0
+    .bdrv_aio_read = raw_aio_read,
+    .bdrv_aio_write = raw_aio_write,
+    .bdrv_aio_cancel = raw_aio_cancel,
+    .aiocb_size = sizeof(RawAIOCB);
+#endif
+    .bdrv_pread = raw_pread,
+    .bdrv_pwrite = raw_pwrite,
+    .bdrv_getlength = raw_getlength,
+};
+#endif /* _WIN32 */
index 4cc3db84a1c4c8b9756316197567f1e4d318dcaf..28df8ae466400c4cf0e6b6f0bf25e3a8cdd0266b 100644 (file)
@@ -22,6 +22,7 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
+
 #include "vl.h"
 #include "block_int.h"
 
@@ -59,7 +60,7 @@ typedef struct {
 #define L2_CACHE_SIZE 16
 
 typedef struct BDRVVmdkState {
-    int fd;
+    BlockDriverState *hd;
     int64_t l1_table_offset;
     int64_t l1_backup_table_offset;
     uint32_t *l1_table;
@@ -73,6 +74,7 @@ typedef struct BDRVVmdkState {
     uint32_t l2_cache_counts[L2_CACHE_SIZE];
 
     unsigned int cluster_sectors;
+    uint32_t parent_cid;
 } BDRVVmdkState;
 
 static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename)
@@ -89,27 +91,278 @@ static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename)
         return 0;
 }
 
-static int vmdk_open(BlockDriverState *bs, const char *filename)
+#define CHECK_CID 1
+
+#define SECTOR_SIZE 512                                
+#define DESC_SIZE 20*SECTOR_SIZE       // 20 sectors of 512 bytes each
+#define HEADER_SIZE 512                        // first sector of 512 bytes 
+
+static uint32_t vmdk_read_cid(BlockDriverState *bs, int parent)
 {
     BDRVVmdkState *s = bs->opaque;
-    int fd, i;
-    uint32_t magic;
-    int l1_size;
+    char desc[DESC_SIZE];
+    uint32_t cid;
+    char *p_name, *cid_str; 
+    size_t cid_str_size;
+
+    /* the descriptor offset = 0x200 */
+    if (bdrv_pread(s->hd, 0x200, desc, DESC_SIZE) != DESC_SIZE)
+        return 0;
+
+    if (parent) {
+        cid_str = "parentCID";
+        cid_str_size = sizeof("parentCID");
+    } else {
+        cid_str = "CID";
+        cid_str_size = sizeof("CID");
+    }
+
+    if ((p_name = strstr(desc,cid_str)) != 0) {
+        p_name += cid_str_size;
+        sscanf(p_name,"%x",&cid);
+    }
+
+    return cid;
+}
+
+static int vmdk_write_cid(BlockDriverState *bs, uint32_t cid)
+{
+    BDRVVmdkState *s = bs->opaque;
+    char desc[DESC_SIZE], tmp_desc[DESC_SIZE];
+    char *p_name, *tmp_str;
+
+    /* the descriptor offset = 0x200 */
+    if (bdrv_pread(s->hd, 0x200, desc, DESC_SIZE) != DESC_SIZE)
+        return -1;
+
+    tmp_str = strstr(desc,"parentCID");
+    strcpy(tmp_desc, tmp_str);
+    if ((p_name = strstr(desc,"CID")) != 0) {
+        p_name += sizeof("CID");
+        sprintf(p_name,"%x\n",cid);
+        strcat(desc,tmp_desc);
+    }
+
+    if (bdrv_pwrite(s->hd, 0x200, desc, DESC_SIZE) != DESC_SIZE)
+        return -1;
+    return 0;
+}
+
+static int vmdk_is_cid_valid(BlockDriverState *bs)
+{
+#ifdef CHECK_CID
+    BDRVVmdkState *s = bs->opaque;
+    BlockDriverState *p_bs = s->hd->backing_hd;
+    uint32_t cur_pcid;
+
+    if (p_bs) {
+        cur_pcid = vmdk_read_cid(p_bs,0);
+        if (s->parent_cid != cur_pcid)
+            // CID not valid
+            return 0;
+    }
+#endif
+    // CID valid
+    return 1;
+}
+
+static int vmdk_snapshot_create(const char *filename, const char *backing_file)
+{
+    int snp_fd, p_fd;
+    uint32_t p_cid;
+    char *p_name, *gd_buf, *rgd_buf; 
+    const char *real_filename, *temp_str;
+    VMDK4Header header;
+    uint32_t gde_entries, gd_size;
+    int64_t gd_offset, rgd_offset, capacity, gt_size;
+    char p_desc[DESC_SIZE], s_desc[DESC_SIZE], hdr[HEADER_SIZE];
+    char *desc_template =
+    "# Disk DescriptorFile\n"
+    "version=1\n"
+    "CID=%x\n"
+    "parentCID=%x\n"
+    "createType=\"monolithicSparse\"\n"
+    "parentFileNameHint=\"%s\"\n"
+    "\n"
+    "# Extent description\n"
+    "RW %lu SPARSE \"%s\"\n"
+    "\n"
+    "# The Disk Data Base \n"
+    "#DDB\n"
+    "\n";
+
+    snp_fd = open(filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, 0644);
+    if (snp_fd < 0)
+        return -1;
+    p_fd = open(backing_file, O_RDONLY | O_BINARY | O_LARGEFILE);
+    if (p_fd < 0) {
+        close(snp_fd);
+        return -1;
+    }
+
+    /* read the header */
+    if (lseek(p_fd, 0x0, SEEK_SET) == -1)
+        goto fail;
+    if (read(p_fd, hdr, HEADER_SIZE) != HEADER_SIZE)
+        goto fail;
+
+    /* write the header */
+    if (lseek(snp_fd, 0x0, SEEK_SET) == -1)
+        goto fail;
+    if (write(snp_fd, hdr, HEADER_SIZE) == -1)
+        goto fail;
+
+    memset(&header, 0, sizeof(header));
+    memcpy(&header,&hdr[4], sizeof(header)); // skip the VMDK4_MAGIC
+
+    ftruncate(snp_fd, header.grain_offset << 9);
+    /* the descriptor offset = 0x200 */
+    if (lseek(p_fd, 0x200, SEEK_SET) == -1)
+        goto fail;
+    if (read(p_fd, p_desc, DESC_SIZE) != DESC_SIZE)
+        goto fail;
+
+    if ((p_name = strstr(p_desc,"CID")) != 0) {
+        p_name += sizeof("CID");
+        sscanf(p_name,"%x",&p_cid);
+    }
+
+    real_filename = filename;
+    if ((temp_str = strrchr(real_filename, '\\')) != NULL)
+        real_filename = temp_str + 1;
+    if ((temp_str = strrchr(real_filename, '/')) != NULL)
+        real_filename = temp_str + 1;
+    if ((temp_str = strrchr(real_filename, ':')) != NULL)
+        real_filename = temp_str + 1;
+
+    sprintf(s_desc, desc_template, p_cid, p_cid, backing_file
+            , (uint32_t)header.capacity, real_filename);
+
+    /* write the descriptor */
+    if (lseek(snp_fd, 0x200, SEEK_SET) == -1)
+        goto fail;
+    if (write(snp_fd, s_desc, strlen(s_desc)) == -1)
+        goto fail;
 
-    fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
-    if (fd < 0) {
-        fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
-        if (fd < 0)
+    gd_offset = header.gd_offset * SECTOR_SIZE;     // offset of GD table
+    rgd_offset = header.rgd_offset * SECTOR_SIZE;   // offset of RGD table
+    capacity = header.capacity * SECTOR_SIZE;       // Extent size
+    /*
+     * Each GDE span 32M disk, means:
+     * 512 GTE per GT, each GTE points to grain
+     */
+    gt_size = (int64_t)header.num_gtes_per_gte * header.granularity * SECTOR_SIZE;
+    if (!gt_size)
+        goto fail;
+    gde_entries = (uint32_t)(capacity / gt_size);  // number of gde/rgde 
+    gd_size = gde_entries * sizeof(uint32_t);
+
+    /* write RGD */
+    rgd_buf = qemu_malloc(gd_size);
+    if (!rgd_buf)
+        goto fail;
+    if (lseek(p_fd, rgd_offset, SEEK_SET) == -1)
+        goto fail_rgd;
+    if (read(p_fd, rgd_buf, gd_size) != gd_size)
+        goto fail_rgd;
+    if (lseek(snp_fd, rgd_offset, SEEK_SET) == -1)
+        goto fail_rgd;
+    if (write(snp_fd, rgd_buf, gd_size) == -1)
+        goto fail_rgd;
+    qemu_free(rgd_buf);
+
+    /* write GD */
+    gd_buf = qemu_malloc(gd_size);
+    if (!gd_buf)
+        goto fail_rgd;
+    if (lseek(p_fd, gd_offset, SEEK_SET) == -1)
+        goto fail_gd;
+    if (read(p_fd, gd_buf, gd_size) != gd_size)
+        goto fail_gd;
+    if (lseek(snp_fd, gd_offset, SEEK_SET) == -1)
+        goto fail_gd;
+    if (write(snp_fd, gd_buf, gd_size) == -1)
+        goto fail_gd;
+    qemu_free(gd_buf);
+
+    close(p_fd);
+    close(snp_fd);
+    return 0;
+
+    fail_gd:
+    qemu_free(gd_buf);
+    fail_rgd:   
+    qemu_free(rgd_buf);
+    fail:
+    close(p_fd);
+    close(snp_fd);
+    return -1;
+}
+
+static void vmdk_parent_close(BlockDriverState *bs)
+{
+    if (bs->backing_hd)
+        bdrv_close(bs->backing_hd);
+}
+
+
+static int vmdk_parent_open(BlockDriverState *bs, const char * filename)
+{
+    BDRVVmdkState *s = bs->opaque;
+    char *p_name; 
+    char desc[DESC_SIZE];
+    char parent_img_name[1024];
+
+    /* the descriptor offset = 0x200 */
+    if (bdrv_pread(s->hd, 0x200, desc, DESC_SIZE) != DESC_SIZE)
+        return -1;
+
+    if ((p_name = strstr(desc,"parentFileNameHint")) != 0) {
+        char *end_name;
+        struct stat file_buf;
+
+        p_name += sizeof("parentFileNameHint") + 1;
+        if ((end_name = strchr(p_name,'\"')) == 0)
+            return -1;
+                
+        strncpy(s->hd->backing_file, p_name, end_name - p_name);
+        if (stat(s->hd->backing_file, &file_buf) != 0) {
+            path_combine(parent_img_name, sizeof(parent_img_name),
+                         filename, s->hd->backing_file);
+        } else {
+            strcpy(parent_img_name, s->hd->backing_file);
+        }
+
+        s->hd->backing_hd = bdrv_new("");
+        if (!s->hd->backing_hd) {
+            failure:
+            bdrv_close(s->hd);
             return -1;
-        bs->read_only = 1;
+        }
+        if (bdrv_open(s->hd->backing_hd, parent_img_name, 0) < 0)
+            goto failure;
     }
-    if (read(fd, &magic, sizeof(magic)) != sizeof(magic))
+
+    return 0;
+}
+
+static int vmdk_open(BlockDriverState *bs, const char *filename, int flags)
+{
+    BDRVVmdkState *s = bs->opaque;
+    uint32_t magic;
+    int l1_size, i, ret;
+
+    ret = bdrv_file_open(&s->hd, filename, flags);
+    if (ret < 0)
+        return ret;
+    if (bdrv_pread(s->hd, 0, &magic, sizeof(magic)) != sizeof(magic))
         goto fail;
+
     magic = be32_to_cpu(magic);
     if (magic == VMDK3_MAGIC) {
         VMDK3Header header;
-        if (read(fd, &header, sizeof(header)) != 
-            sizeof(header))
+
+        if (bdrv_pread(s->hd, sizeof(magic), &header, sizeof(header)) != sizeof(header))
             goto fail;
         s->cluster_sectors = le32_to_cpu(header.granularity);
         s->l2_size = 1 << 9;
@@ -120,8 +373,8 @@ static int vmdk_open(BlockDriverState *bs, const char *filename)
         s->l1_entry_sectors = s->l2_size * s->cluster_sectors;
     } else if (magic == VMDK4_MAGIC) {
         VMDK4Header header;
-        
-        if (read(fd, &header, sizeof(header)) != sizeof(header))
+
+        if (bdrv_pread(s->hd, sizeof(magic), &header, sizeof(header)) != sizeof(header))
             goto fail;
         bs->total_sectors = le64_to_cpu(header.capacity);
         s->cluster_sectors = le64_to_cpu(header.granularity);
@@ -133,17 +386,22 @@ static int vmdk_open(BlockDriverState *bs, const char *filename)
             / s->l1_entry_sectors;
         s->l1_table_offset = le64_to_cpu(header.rgd_offset) << 9;
         s->l1_backup_table_offset = le64_to_cpu(header.gd_offset) << 9;
+
+        // try to open parent images, if exist
+        if (vmdk_parent_open(bs, filename) != 0)
+            goto fail;
+        // write the CID once after the image creation
+        s->parent_cid = vmdk_read_cid(bs,1);
     } else {
         goto fail;
     }
+
     /* read the L1 table */
     l1_size = s->l1_size * sizeof(uint32_t);
     s->l1_table = qemu_malloc(l1_size);
     if (!s->l1_table)
         goto fail;
-    if (lseek(fd, s->l1_table_offset, SEEK_SET) == -1)
-        goto fail;
-    if (read(fd, s->l1_table, l1_size) != l1_size)
+    if (bdrv_pread(s->hd, s->l1_table_offset, s->l1_table, l1_size) != l1_size)
         goto fail;
     for(i = 0; i < s->l1_size; i++) {
         le32_to_cpus(&s->l1_table[i]);
@@ -153,9 +411,7 @@ static int vmdk_open(BlockDriverState *bs, const char *filename)
         s->l1_backup_table = qemu_malloc(l1_size);
         if (!s->l1_backup_table)
             goto fail;
-        if (lseek(fd, s->l1_backup_table_offset, SEEK_SET) == -1)
-            goto fail;
-        if (read(fd, s->l1_backup_table, l1_size) != l1_size)
+        if (bdrv_pread(s->hd, s->l1_backup_table_offset, s->l1_backup_table, l1_size) != l1_size)
             goto fail;
         for(i = 0; i < s->l1_size; i++) {
             le32_to_cpus(&s->l1_backup_table[i]);
@@ -165,16 +421,43 @@ static int vmdk_open(BlockDriverState *bs, const char *filename)
     s->l2_cache = qemu_malloc(s->l2_size * L2_CACHE_SIZE * sizeof(uint32_t));
     if (!s->l2_cache)
         goto fail;
-    s->fd = fd;
     return 0;
  fail:
     qemu_free(s->l1_backup_table);
     qemu_free(s->l1_table);
     qemu_free(s->l2_cache);
-    close(fd);
+    bdrv_delete(s->hd);
     return -1;
 }
 
+static uint64_t get_cluster_offset(BlockDriverState *bs, uint64_t offset, int allocate);
+
+static int get_whole_cluster(BlockDriverState *bs, uint64_t cluster_offset,
+                             uint64_t offset, int allocate)
+{
+    uint64_t parent_cluster_offset;
+    BDRVVmdkState *s = bs->opaque;
+    uint8_t  whole_grain[s->cluster_sectors*512];        // 128 sectors * 512 bytes each = grain size 64KB
+
+    // we will be here if it's first write on non-exist grain(cluster).
+    // try to read from parent image, if exist
+    if (s->hd->backing_hd) {
+        BDRVVmdkState *ps = s->hd->backing_hd->opaque;
+
+        if (!vmdk_is_cid_valid(bs))
+            return -1;
+        parent_cluster_offset = get_cluster_offset(s->hd->backing_hd, offset, allocate);
+        if (bdrv_pread(ps->hd, parent_cluster_offset, whole_grain, ps->cluster_sectors*512) != 
+                                                                            ps->cluster_sectors*512)
+            return -1;
+
+        if (bdrv_pwrite(s->hd, cluster_offset << 9, whole_grain, sizeof(whole_grain)) != 
+                                                                            sizeof(whole_grain))
+            return -1;
+    }
+    return 0;
+}
+
 static uint64_t get_cluster_offset(BlockDriverState *bs,
                                    uint64_t offset, int allocate)
 {
@@ -212,34 +495,41 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
         }
     }
     l2_table = s->l2_cache + (min_index * s->l2_size);
-    lseek(s->fd, (int64_t)l2_offset * 512, SEEK_SET);
-    if (read(s->fd, l2_table, s->l2_size * sizeof(uint32_t)) != 
-        s->l2_size * sizeof(uint32_t))
+    if (bdrv_pread(s->hd, (int64_t)l2_offset * 512, l2_table, s->l2_size * sizeof(uint32_t)) != 
+                                                                        s->l2_size * sizeof(uint32_t))
         return 0;
+
     s->l2_cache_offsets[min_index] = l2_offset;
     s->l2_cache_counts[min_index] = 1;
  found:
     l2_index = ((offset >> 9) / s->cluster_sectors) % s->l2_size;
     cluster_offset = le32_to_cpu(l2_table[l2_index]);
     if (!cluster_offset) {
+        struct stat file_buf;
+
         if (!allocate)
             return 0;
-        cluster_offset = lseek(s->fd, 0, SEEK_END);
-        ftruncate(s->fd, cluster_offset + (s->cluster_sectors << 9));
+        stat(s->hd->filename, &file_buf);
+        cluster_offset = file_buf.st_size;
+        bdrv_truncate(s->hd, cluster_offset + (s->cluster_sectors << 9));
+
         cluster_offset >>= 9;
         /* update L2 table */
         tmp = cpu_to_le32(cluster_offset);
         l2_table[l2_index] = tmp;
-        lseek(s->fd, ((int64_t)l2_offset * 512) + (l2_index * sizeof(tmp)), SEEK_SET);
-        if (write(s->fd, &tmp, sizeof(tmp)) != sizeof(tmp))
+        if (bdrv_pwrite(s->hd, ((int64_t)l2_offset * 512) + (l2_index * sizeof(tmp)), 
+                        &tmp, sizeof(tmp)) != sizeof(tmp))
             return 0;
         /* update backup L2 table */
         if (s->l1_backup_table_offset != 0) {
             l2_offset = s->l1_backup_table[l1_index];
-            lseek(s->fd, ((int64_t)l2_offset * 512) + (l2_index * sizeof(tmp)), SEEK_SET);
-            if (write(s->fd, &tmp, sizeof(tmp)) != sizeof(tmp))
+            if (bdrv_pwrite(s->hd, ((int64_t)l2_offset * 512) + (l2_index * sizeof(tmp)), 
+                            &tmp, sizeof(tmp)) != sizeof(tmp))
                 return 0;
         }
+
+        if (get_whole_cluster(bs, cluster_offset, offset, allocate) == -1)
+            return 0;
     }
     cluster_offset <<= 9;
     return cluster_offset;
@@ -265,9 +555,9 @@ static int vmdk_read(BlockDriverState *bs, int64_t sector_num,
                     uint8_t *buf, int nb_sectors)
 {
     BDRVVmdkState *s = bs->opaque;
-    int ret, index_in_cluster, n;
+    int index_in_cluster, n, ret;
     uint64_t cluster_offset;
-    
+
     while (nb_sectors > 0) {
         cluster_offset = get_cluster_offset(bs, sector_num << 9, 0);
         index_in_cluster = sector_num % s->cluster_sectors;
@@ -275,11 +565,18 @@ static int vmdk_read(BlockDriverState *bs, int64_t sector_num,
         if (n > nb_sectors)
             n = nb_sectors;
         if (!cluster_offset) {
-            memset(buf, 0, 512 * n);
+            // try to read from parent image, if exist
+            if (s->hd->backing_hd) {
+                if (!vmdk_is_cid_valid(bs))
+                    return -1;
+                ret = bdrv_read(s->hd->backing_hd, sector_num, buf, n);
+                if (ret < 0)
+                    return -1;
+            } else {
+                memset(buf, 0, 512 * n);
+            }
         } else {
-            lseek(s->fd, cluster_offset + index_in_cluster * 512, SEEK_SET);
-            ret = read(s->fd, buf, n * 512);
-            if (ret != n * 512) 
+            if(bdrv_pread(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512) != n * 512)
                 return -1;
         }
         nb_sectors -= n;
@@ -293,8 +590,9 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
                      const uint8_t *buf, int nb_sectors)
 {
     BDRVVmdkState *s = bs->opaque;
-    int ret, index_in_cluster, n;
+    int index_in_cluster, n;
     uint64_t cluster_offset;
+    static int cid_update = 0;
 
     while (nb_sectors > 0) {
         index_in_cluster = sector_num & (s->cluster_sectors - 1);
@@ -304,13 +602,17 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
         cluster_offset = get_cluster_offset(bs, sector_num << 9, 1);
         if (!cluster_offset)
             return -1;
-        lseek(s->fd, cluster_offset + index_in_cluster * 512, SEEK_SET);
-        ret = write(s->fd, buf, n * 512);
-        if (ret != n * 512)
+        if (bdrv_pwrite(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512) != n * 512)
             return -1;
         nb_sectors -= n;
         sector_num += n;
         buf += n * 512;
+
+        // update CID on the first write every time the virtual disk is opened
+        if (!cid_update) {
+            vmdk_write_cid(bs, time(NULL));
+            cid_update++;
+        }
     }
     return 0;
 }
@@ -334,7 +636,7 @@ static int vmdk_create(const char *filename, int64_t total_size,
         "# The Disk Data Base \n"
         "#DDB\n"
         "\n"
-        "ddb.virtualHWVersion = \"3\"\n"
+        "ddb.virtualHWVersion = \"4\"\n"
         "ddb.geometry.cylinders = \"%lu\"\n"
         "ddb.geometry.heads = \"16\"\n"
         "ddb.geometry.sectors = \"63\"\n"
@@ -343,6 +645,9 @@ static int vmdk_create(const char *filename, int64_t total_size,
     const char *real_filename, *temp_str;
 
     /* XXX: add support for backing file */
+    if (backing_file) {
+        return vmdk_snapshot_create(filename, backing_file);
+    }
 
     fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
               0644);
@@ -421,15 +726,18 @@ static int vmdk_create(const char *filename, int64_t total_size,
 static void vmdk_close(BlockDriverState *bs)
 {
     BDRVVmdkState *s = bs->opaque;
+
     qemu_free(s->l1_table);
     qemu_free(s->l2_cache);
-    close(s->fd);
+    bdrv_delete(s->hd);
+    // try to close parent image, if exist
+    vmdk_parent_close(s->hd);
 }
 
 static void vmdk_flush(BlockDriverState *bs)
 {
     BDRVVmdkState *s = bs->opaque;
-    fsync(s->fd);
+    bdrv_flush(s->hd);
 }
 
 BlockDriver bdrv_vmdk = {
index bdc3b8891c38c05442e7c6981cc74a68767a7a56..4d228c5b628385253123b40d5e9a21d52051792b 100644 (file)
@@ -86,19 +86,16 @@ static int vpc_probe(const uint8_t *buf, int buf_size, const char *filename)
     return 0;
 }
 
-static int vpc_open(BlockDriverState *bs, const char *filename)
+static int vpc_open(BlockDriverState *bs, const char *filename, int flags)
 {
     BDRVVPCState *s = bs->opaque;
     int fd, i;
     struct vpc_subheader header;
 
-    fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
-    if (fd < 0) {
-        fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
-        if (fd < 0)
-            return -1;
-    }
-    
+    fd = open(filename, O_RDONLY | O_BINARY);
+    if (fd < 0)
+        return -1;
+
     bs->read_only = 1; // no write support yet
     
     s->fd = fd;
index 9dedf9115fbc321ddfa2e5e670195826f86d2b3d..48a52e3116cfcd06b5b3bac04dbd059d46e05d5b 100644 (file)
@@ -61,7 +61,7 @@ void nonono(const char* file, int line, const char* msg) {
     exit(-5);
 }
 #undef assert
-#define assert(a) if (!(a)) nonono(__FILE__, __LINE__, #a)
+#define assert(a) do {if (!(a)) nonono(__FILE__, __LINE__, #a);}while(0)
 #endif
 
 #else
@@ -351,13 +351,6 @@ typedef struct BDRVVVFATState {
 } BDRVVVFATState;
 
 
-static int vvfat_probe(const uint8_t *buf, int buf_size, const char *filename)
-{
-    if (strstart(filename, "fat:", NULL))
-       return 100;
-    return 0;
-}
-
 static void init_mbr(BDRVVVFATState* s)
 {
     /* TODO: if the files mbr.img and bootsect.img exist, use them */
@@ -954,18 +947,22 @@ static int init_directories(BDRVVVFATState* s,
     return 0;
 }
 
+#ifdef DEBUG
 static BDRVVVFATState *vvv = NULL;
+#endif
 
 static int enable_write_target(BDRVVVFATState *s);
 static int is_consistent(BDRVVVFATState *s);
 
-static int vvfat_open(BlockDriverState *bs, const char* dirname)
+static int vvfat_open(BlockDriverState *bs, const char* dirname, int flags)
 {
     BDRVVVFATState *s = bs->opaque;
     int floppy = 0;
     int i;
 
+#ifdef DEBUG
     vvv = s;
+#endif
 
 DLOG(if (stderr == NULL) {
     stderr = fopen("vvfat.log", "a");
@@ -1040,7 +1037,6 @@ DLOG(if (stderr == NULL) {
        bs->heads = bs->cyls = bs->secs = 0;
 
     //    assert(is_consistent(s));
-
     return 0;
 }
 
@@ -2178,7 +2174,7 @@ static int commit_one_file(BDRVVVFATState* s,
     for (i = s->cluster_size; i < offset; i += s->cluster_size)
        c = modified_fat_get(s, c);
 
-    fd = open(mapping->path, O_RDWR | O_CREAT, 0666);
+    fd = open(mapping->path, O_RDWR | O_CREAT | O_BINARY, 0666);
     if (fd < 0) {
        fprintf(stderr, "Could not open %s... (%s, %d)\n", mapping->path,
                strerror(errno), errno);
@@ -2732,8 +2728,7 @@ static int enable_write_target(BDRVVVFATState *s)
     array_init(&(s->commits), sizeof(commit_t));
 
     s->qcow_filename = malloc(1024);
-    strcpy(s->qcow_filename, "/tmp/vl.XXXXXX");
-    get_tmp_filename(s->qcow_filename, strlen(s->qcow_filename) + 1);
+    get_tmp_filename(s->qcow_filename, 1024);
     if (bdrv_create(&bdrv_qcow,
                s->qcow_filename, s->sector_count, "fat:", 0) < 0)
        return -1;
@@ -2767,14 +2762,15 @@ static void vvfat_close(BlockDriverState *bs)
 BlockDriver bdrv_vvfat = {
     "vvfat",
     sizeof(BDRVVVFATState),
-    vvfat_probe,
+    NULL, /* no probe for protocols */
     vvfat_open,
     vvfat_read,
     vvfat_write,
     vvfat_close,
     NULL, /* ??? Not sure if we can do any meaningful flushing.  */
     NULL,
-    vvfat_is_allocated
+    vvfat_is_allocated,
+    .protocol_name = "fat",
 };
 
 #ifdef DEBUG
index 34757f455709809b14b0df3446cc48baacb41cba..cf84e8ffbb620dac4fe9cd6cf4c6bc5d96e3aaad 100644 (file)
 #include <sys/disk.h>
 #endif
 
-#ifdef CONFIG_COCOA
-#include <paths.h>
-#include <sys/param.h>
-#include <IOKit/IOKitLib.h>
-#include <IOKit/IOBSD.h>
-#include <IOKit/storage/IOMediaBSDClient.h>
-#include <IOKit/storage/IOMedia.h>
-#include <IOKit/storage/IOCDMedia.h>
-//#include <IOKit/storage/IOCDTypes.h>
-#include <CoreFoundation/CoreFoundation.h>
-#endif
+#define SECTOR_BITS 9
+#define SECTOR_SIZE (1 << SECTOR_BITS)
 
-#ifdef __sun__
-#include <sys/dkio.h>
-#endif
+typedef struct BlockDriverAIOCBSync {
+    BlockDriverAIOCB common;
+    QEMUBH *bh;
+    int ret;
+} BlockDriverAIOCBSync;
+
+static BlockDriverAIOCB *bdrv_aio_read_em(BlockDriverState *bs,
+        int64_t sector_num, uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque);
+static BlockDriverAIOCB *bdrv_aio_write_em(BlockDriverState *bs,
+        int64_t sector_num, const uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque);
+static void bdrv_aio_cancel_em(BlockDriverAIOCB *acb);
+static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num, 
+                        uint8_t *buf, int nb_sectors);
+static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
+                         const uint8_t *buf, int nb_sectors);
 
 static BlockDriverState *bdrv_first;
 static BlockDriver *first_drv;
 
-#ifdef CONFIG_COCOA
-static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator );
-static kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize );
-
-kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator )
+int path_is_absolute(const char *path)
 {
-    kern_return_t       kernResult; 
-    mach_port_t     masterPort;
-    CFMutableDictionaryRef  classesToMatch;
-
-    kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort );
-    if ( KERN_SUCCESS != kernResult ) {
-        printf( "IOMasterPort returned %d\n", kernResult );
-    }
-    
-    classesToMatch = IOServiceMatching( kIOCDMediaClass ); 
-    if ( classesToMatch == NULL ) {
-        printf( "IOServiceMatching returned a NULL dictionary.\n" );
-    } else {
-    CFDictionarySetValue( classesToMatch, CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue );
-    }
-    kernResult = IOServiceGetMatchingServices( masterPort, classesToMatch, mediaIterator );
-    if ( KERN_SUCCESS != kernResult )
-    {
-        printf( "IOServiceGetMatchingServices returned %d\n", kernResult );
-    }
-    
-    return kernResult;
+    const char *p;
+#ifdef _WIN32
+    /* specific case for names like: "\\.\d:" */
+    if (*path == '/' || *path == '\\')
+        return 1;
+#endif
+    p = strchr(path, ':');
+    if (p)
+        p++;
+    else
+        p = path;
+#ifdef _WIN32
+    return (*p == '/' || *p == '\\');
+#else
+    return (*p == '/');
+#endif
 }
 
-kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize )
+/* if filename is absolute, just copy it to dest. Otherwise, build a
+   path to it by considering it is relative to base_path. URL are
+   supported. */
+void path_combine(char *dest, int dest_size,
+                  const char *base_path,
+                  const char *filename)
 {
-    io_object_t     nextMedia;
-    kern_return_t   kernResult = KERN_FAILURE;
-    *bsdPath = '\0';
-    nextMedia = IOIteratorNext( mediaIterator );
-    if ( nextMedia )
-    {
-        CFTypeRef   bsdPathAsCFString;
-    bsdPathAsCFString = IORegistryEntryCreateCFProperty( nextMedia, CFSTR( kIOBSDNameKey ), kCFAllocatorDefault, 0 );
-        if ( bsdPathAsCFString ) {
-            size_t devPathLength;
-            strcpy( bsdPath, _PATH_DEV );
-            strcat( bsdPath, "r" );
-            devPathLength = strlen( bsdPath );
-            if ( CFStringGetCString( bsdPathAsCFString, bsdPath + devPathLength, maxPathSize - devPathLength, kCFStringEncodingASCII ) ) {
-                kernResult = KERN_SUCCESS;
-            }
-            CFRelease( bsdPathAsCFString );
+    const char *p, *p1;
+    int len;
+
+    if (dest_size <= 0)
+        return;
+    if (path_is_absolute(filename)) {
+        pstrcpy(dest, dest_size, filename);
+    } else {
+        p = strchr(base_path, ':');
+        if (p)
+            p++;
+        else
+            p = base_path;
+        p1 = strrchr(base_path, '/');
+#ifdef _WIN32
+        {
+            const char *p2;
+            p2 = strrchr(base_path, '\\');
+            if (!p1 || p2 > p1)
+                p1 = p2;
         }
-        IOObjectRelease( nextMedia );
+#endif
+        if (p1)
+            p1++;
+        else
+            p1 = base_path;
+        if (p1 > p)
+            p = p1;
+        len = p - base_path;
+        if (len > dest_size - 1)
+            len = dest_size - 1;
+        memcpy(dest, base_path, len);
+        dest[len] = '\0';
+        pstrcat(dest, dest_size, filename);
     }
-    
-    return kernResult;
 }
 
-#endif
 
 void bdrv_register(BlockDriver *bdrv)
 {
+    if (!bdrv->bdrv_aio_read) {
+        /* add AIO emulation layer */
+        bdrv->bdrv_aio_read = bdrv_aio_read_em;
+        bdrv->bdrv_aio_write = bdrv_aio_write_em;
+        bdrv->bdrv_aio_cancel = bdrv_aio_cancel_em;
+        bdrv->aiocb_size = sizeof(BlockDriverAIOCBSync);
+    } else if (!bdrv->bdrv_read && !bdrv->bdrv_pread) {
+        /* add synchronous IO emulation layer */
+        bdrv->bdrv_read = bdrv_read_em;
+        bdrv->bdrv_write = bdrv_write_em;
+    }
     bdrv->next = first_drv;
     first_drv = bdrv;
 }
@@ -156,14 +179,10 @@ int bdrv_create(BlockDriver *drv,
 #ifdef _WIN32
 void get_tmp_filename(char *filename, int size)
 {
-    char* p = strrchr(filename, '/');
-
-    if (p == NULL)
-       return;
-
-    /* XXX: find a better function */
-    tmpnam(p);
-    *p = '/';
+    char temp_dir[MAX_PATH];
+    
+    GetTempPath(MAX_PATH, temp_dir);
+    GetTempFileName(temp_dir, "qem", 0, filename);
 }
 #else
 void get_tmp_filename(char *filename, int size)
@@ -176,101 +195,141 @@ void get_tmp_filename(char *filename, int size)
 }
 #endif
 
+#ifdef _WIN32
+static int is_windows_drive_prefix(const char *filename)
+{
+    return (((filename[0] >= 'a' && filename[0] <= 'z') ||
+             (filename[0] >= 'A' && filename[0] <= 'Z')) &&
+            filename[1] == ':');
+}
+    
+static int is_windows_drive(const char *filename)
+{
+    if (is_windows_drive_prefix(filename) && 
+        filename[2] == '\0')
+        return 1;
+    if (strstart(filename, "\\\\.\\", NULL) ||
+        strstart(filename, "//./", NULL))
+        return 1;
+    return 0;
+}
+#endif
+
+static BlockDriver *find_protocol(const char *filename)
+{
+    BlockDriver *drv1;
+    char protocol[128];
+    int len;
+    const char *p;
+
+#ifdef _WIN32
+    if (is_windows_drive(filename) ||
+        is_windows_drive_prefix(filename))
+        return &bdrv_raw;
+#endif
+    p = strchr(filename, ':');
+    if (!p)
+        return &bdrv_raw;
+    len = p - filename;
+    if (len > sizeof(protocol) - 1)
+        len = sizeof(protocol) - 1;
+    memcpy(protocol, filename, len);
+    protocol[len] = '\0';
+    for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
+        if (drv1->protocol_name && 
+            !strcmp(drv1->protocol_name, protocol))
+            return drv1;
+    }
+    return NULL;
+}
+
 /* XXX: force raw format if block or character device ? It would
    simplify the BSD case */
 static BlockDriver *find_image_format(const char *filename)
 {
-    int fd, ret, score, score_max;
+    int ret, score, score_max;
     BlockDriver *drv1, *drv;
-    uint8_t *buf;
-    size_t bufsize = 1024;
-
-    fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
-    if (fd < 0) {
-        buf = NULL;
-        ret = 0;
-    } else {
-#ifdef DIOCGSECTORSIZE
-        {
-            unsigned int sectorsize = 512;
-            if (!ioctl(fd, DIOCGSECTORSIZE, &sectorsize) &&
-                sectorsize > bufsize)
-                bufsize = sectorsize;
-        }
-#endif
-#ifdef CONFIG_COCOA
-        u_int32_t   blockSize = 512;
-        if ( !ioctl( fd, DKIOCGETBLOCKSIZE, &blockSize ) && blockSize > bufsize) {
-            bufsize = blockSize;
-        }
-#endif
-        buf = qemu_malloc(bufsize);
-        if (!buf)
-            return NULL;
-        ret = read(fd, buf, bufsize);
-        if (ret < 0) {
-            close(fd);
-            qemu_free(buf);
-            return NULL;
+    uint8_t buf[2048];
+    BlockDriverState *bs;
+    
+    /* detect host devices. By convention, /dev/cdrom[N] is always
+       recognized as a host CDROM */
+    if (strstart(filename, "/dev/cdrom", NULL))
+        return &bdrv_host_device;
+#ifdef _WIN32
+    if (is_windows_drive(filename))
+        return &bdrv_host_device;
+#else
+    {
+        struct stat st;
+        if (stat(filename, &st) >= 0 && 
+            (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))) {
+            return &bdrv_host_device;
         }
-        close(fd);
     }
+#endif
     
-    drv = NULL;
+    drv = find_protocol(filename);
+    /* no need to test disk image formats for vvfat */
+    if (drv == &bdrv_vvfat)
+        return drv;
+
+    ret = bdrv_file_open(&bs, filename, BDRV_O_RDONLY);
+    if (ret < 0)
+        return NULL;
+    ret = bdrv_pread(bs, 0, buf, sizeof(buf));
+    bdrv_delete(bs);
+    if (ret < 0) {
+        return NULL;
+    }
+
     score_max = 0;
     for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
-        score = drv1->bdrv_probe(buf, ret, filename);
-        if (score > score_max) {
-            score_max = score;
-            drv = drv1;
+        if (drv1->bdrv_probe) {
+            score = drv1->bdrv_probe(buf, ret, filename);
+            if (score > score_max) {
+                score_max = score;
+                drv = drv1;
+            }
         }
     }
-    qemu_free(buf);
     return drv;
 }
 
-int bdrv_open(BlockDriverState *bs, const char *filename, int snapshot)
+int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags)
 {
-#ifdef CONFIG_COCOA
-    if ( strncmp( filename, "/dev/cdrom", 10 ) == 0 ) {
-        kern_return_t kernResult;
-        io_iterator_t mediaIterator;
-        char bsdPath[ MAXPATHLEN ];
-        int fd;
-        kernResult = FindEjectableCDMedia( &mediaIterator );
-        kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof( bsdPath ) );
-    
-        if ( bsdPath[ 0 ] != '\0' ) {
-            strcat(bsdPath,"s0");
-            /* some CDs don't have a partition 0 */
-            fd = open(bsdPath, O_RDONLY | O_BINARY | O_LARGEFILE);
-            if (fd < 0) {
-                bsdPath[strlen(bsdPath)-1] = '1';
-            } else {
-                close(fd);
-            }
-            filename = bsdPath;
-        }
-        
-        if ( mediaIterator )
-            IOObjectRelease( mediaIterator );
+    BlockDriverState *bs;
+    int ret;
+
+    bs = bdrv_new("");
+    if (!bs)
+        return -ENOMEM;
+    ret = bdrv_open2(bs, filename, flags | BDRV_O_FILE, NULL);
+    if (ret < 0) {
+        bdrv_delete(bs);
+        return ret;
     }
-#endif
-    return bdrv_open2(bs, filename, snapshot, NULL);
+    *pbs = bs;
+    return 0;
 }
 
-int bdrv_open2(BlockDriverState *bs, const char *filename, int snapshot,
+int bdrv_open(BlockDriverState *bs, const char *filename, int flags)
+{
+    return bdrv_open2(bs, filename, flags, NULL);
+}
+
+int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
                BlockDriver *drv)
 {
-    int ret;
+    int ret, open_flags;
     char tmp_filename[1024];
+    char backing_filename[1024];
     
     bs->read_only = 0;
     bs->is_temporary = 0;
     bs->encrypted = 0;
 
-    if (snapshot) {
+    if (flags & BDRV_O_SNAPSHOT) {
         BlockDriverState *bs1;
         int64_t total_size;
         
@@ -280,19 +339,19 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int snapshot,
         /* if there is a backing file, use it */
         bs1 = bdrv_new("");
         if (!bs1) {
-            return -1;
+            return -ENOMEM;
         }
         if (bdrv_open(bs1, filename, 0) < 0) {
             bdrv_delete(bs1);
             return -1;
         }
-        total_size = bs1->total_sectors;
+        total_size = bdrv_getlength(bs1) >> SECTOR_BITS;
         bdrv_delete(bs1);
         
         get_tmp_filename(tmp_filename, sizeof(tmp_filename));
-        /* XXX: use cow for linux as it is more efficient ? */
-        if (bdrv_create(&bdrv_qcow, tmp_filename, 
-                        total_size, filename, 0) < 0) {
+        realpath(filename, backing_filename);
+        if (bdrv_create(&bdrv_qcow2, tmp_filename, 
+                        total_size, backing_filename, 0) < 0) {
             return -1;
         }
         filename = tmp_filename;
@@ -300,41 +359,62 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int snapshot,
     }
 
     pstrcpy(bs->filename, sizeof(bs->filename), filename);
-    if (!drv) {
-        drv = find_image_format(filename);
+    if (flags & BDRV_O_FILE) {
+        drv = find_protocol(filename);
         if (!drv)
-            return -1;
+            return -ENOENT;
+    } else {
+        if (!drv) {
+            drv = find_image_format(filename);
+            if (!drv)
+                return -1;
+        }
     }
     bs->drv = drv;
     bs->opaque = qemu_mallocz(drv->instance_size);
     if (bs->opaque == NULL && drv->instance_size > 0)
         return -1;
-    
-    ret = drv->bdrv_open(bs, filename);
+    /* Note: for compatibility, we open disk image files as RDWR, and
+       RDONLY as fallback */
+    if (!(flags & BDRV_O_FILE))
+        open_flags = BDRV_O_RDWR;
+    else
+        open_flags = flags & ~(BDRV_O_FILE | BDRV_O_SNAPSHOT);
+    ret = drv->bdrv_open(bs, filename, open_flags);
+    if (ret == -EACCES && !(flags & BDRV_O_FILE)) {
+        ret = drv->bdrv_open(bs, filename, BDRV_O_RDONLY);
+        bs->read_only = 1;
+    }
     if (ret < 0) {
         qemu_free(bs->opaque);
-        return -1;
+        bs->opaque = NULL;
+        bs->drv = NULL;
+        return ret;
+    }
+    if (drv->bdrv_getlength) {
+        bs->total_sectors = bdrv_getlength(bs) >> SECTOR_BITS;
     }
 #ifndef _WIN32
     if (bs->is_temporary) {
         unlink(filename);
     }
 #endif
-    if (bs->backing_file[0] != '\0' && drv->bdrv_is_allocated) {
+    if (bs->backing_file[0] != '\0') {
         /* if there is a backing file, use it */
         bs->backing_hd = bdrv_new("");
         if (!bs->backing_hd) {
         fail:
             bdrv_close(bs);
-            return -1;
+            return -ENOMEM;
         }
-        if (bdrv_open(bs->backing_hd, bs->backing_file, 0) < 0)
+        path_combine(backing_filename, sizeof(backing_filename),
+                     filename, bs->backing_file);
+        if (bdrv_open(bs->backing_hd, backing_filename, 0) < 0)
             goto fail;
     }
 
-    bs->inserted = 1;
-
     /* call the change callback */
+    bs->media_changed = 1;
     if (bs->change_cb)
         bs->change_cb(bs->change_opaque);
 
@@ -343,7 +423,7 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int snapshot,
 
 void bdrv_close(BlockDriverState *bs)
 {
-    if (bs->inserted) {
+    if (bs->drv) {
         if (bs->backing_hd)
             bdrv_delete(bs->backing_hd);
         bs->drv->bdrv_close(bs);
@@ -355,9 +435,9 @@ void bdrv_close(BlockDriverState *bs)
 #endif
         bs->opaque = NULL;
         bs->drv = NULL;
-        bs->inserted = 0;
 
         /* call the change callback */
+        bs->media_changed = 1;
         if (bs->change_cb)
             bs->change_cb(bs->change_opaque);
     }
@@ -373,12 +453,13 @@ void bdrv_delete(BlockDriverState *bs)
 /* commit COW file into the raw image */
 int bdrv_commit(BlockDriverState *bs)
 {
-    int64_t i;
+    BlockDriver *drv = bs->drv;
+    int64_t i, total_sectors;
     int n, j;
     unsigned char sector[512];
 
-    if (!bs->inserted)
-        return -ENOENT;
+    if (!drv)
+        return -ENOMEDIUM;
 
     if (bs->read_only) {
        return -EACCES;
@@ -388,8 +469,9 @@ int bdrv_commit(BlockDriverState *bs)
        return -ENOTSUP;
     }
 
-    for (i = 0; i < bs->total_sectors;) {
-        if (bs->drv->bdrv_is_allocated(bs, i, 65536, &n)) {
+    total_sectors = bdrv_getlength(bs) >> SECTOR_BITS;
+    for (i = 0; i < total_sectors;) {
+        if (drv->bdrv_is_allocated(bs, i, 65536, &n)) {
             for(j = 0; j < n; j++) {
                 if (bdrv_read(bs, i, sector, 1) != 0) {
                     return -EIO;
@@ -405,72 +487,241 @@ int bdrv_commit(BlockDriverState *bs)
         }
     }
 
-    if (bs->drv->bdrv_make_empty)
-       return bs->drv->bdrv_make_empty(bs);
+    if (drv->bdrv_make_empty)
+       return drv->bdrv_make_empty(bs);
 
     return 0;
 }
 
-/* return -1 if error */
+/* return < 0 if error. See bdrv_write() for the return codes */
 int bdrv_read(BlockDriverState *bs, int64_t sector_num, 
               uint8_t *buf, int nb_sectors)
 {
-    int ret, n;
     BlockDriver *drv = bs->drv;
 
-    if (!bs->inserted)
-        return -1;
+    if (!drv)
+        return -ENOMEDIUM;
+
     if (sector_num < 0)
-       return -1;
+       return -EINVAL;
 
-    while (nb_sectors > 0) {
-        if (sector_num == 0 && bs->boot_sector_enabled) {
+    if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
             memcpy(buf, bs->boot_sector_data, 512);
-            n = 1;
-        } else if (bs->backing_hd) {
-            if (drv->bdrv_is_allocated(bs, sector_num, nb_sectors, &n)) {
-                ret = drv->bdrv_read(bs, sector_num, buf, n);
-                if (ret < 0)
-                    return -1;
-            } else {
-                /* read from the base image */
-                ret = bdrv_read(bs->backing_hd, sector_num, buf, n);
-                if (ret < 0)
-                    return -1;
-            }
-        } else {
-            ret = drv->bdrv_read(bs, sector_num, buf, nb_sectors);
-            if (ret < 0)
-                return -1;
-            /* no need to loop */
-            break;
-        }
-        nb_sectors -= n;
-        sector_num += n;
-        buf += n * 512;
+        sector_num++;
+        nb_sectors--;
+        buf += 512;
+        if (nb_sectors == 0)
+            return 0;
+    }
+    if (drv->bdrv_pread) {
+        int ret, len;
+        len = nb_sectors * 512;
+        ret = drv->bdrv_pread(bs, sector_num * 512, buf, len);
+        if (ret < 0)
+            return ret;
+        else if (ret != len)
+            return -EINVAL;
+        else
+            return 0;
+    } else {
+        return drv->bdrv_read(bs, sector_num, buf, nb_sectors);
     }
-    return 0;
 }
 
-/* return -1 if error */
+/* Return < 0 if error. Important errors are: 
+  -EIO         generic I/O error (may happen for all errors)
+  -ENOMEDIUM   No media inserted.
+  -EINVAL      Invalid sector number or nb_sectors
+  -EACCES      Trying to write a read-only device
+*/
 int bdrv_write(BlockDriverState *bs, int64_t sector_num, 
                const uint8_t *buf, int nb_sectors)
 {
-    if (!bs->inserted)
-        return -1;
+    BlockDriver *drv = bs->drv;
+    if (!bs->drv)
+        return -ENOMEDIUM;
     if (bs->read_only)
-        return -1;
+        return -EACCES;
     if (sector_num < 0)
-       return -1;
+       return -EINVAL;
     if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
         memcpy(bs->boot_sector_data, buf, 512);   
     }
-    return bs->drv->bdrv_write(bs, sector_num, buf, nb_sectors);
+    if (drv->bdrv_pwrite) {
+        int ret, len;
+        len = nb_sectors * 512;
+        ret = drv->bdrv_pwrite(bs, sector_num * 512, buf, len);
+        if (ret < 0)
+            return ret;
+        else if (ret != len)
+            return -EIO;
+        else
+            return 0;
+    } else {
+        return drv->bdrv_write(bs, sector_num, buf, nb_sectors);
+    }
+}
+
+static int bdrv_pread_em(BlockDriverState *bs, int64_t offset, 
+                         uint8_t *buf, int count1)
+{
+    uint8_t tmp_buf[SECTOR_SIZE];
+    int len, nb_sectors, count;
+    int64_t sector_num;
+
+    count = count1;
+    /* first read to align to sector start */
+    len = (SECTOR_SIZE - offset) & (SECTOR_SIZE - 1);
+    if (len > count)
+        len = count;
+    sector_num = offset >> SECTOR_BITS;
+    if (len > 0) {
+        if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
+            return -EIO;
+        memcpy(buf, tmp_buf + (offset & (SECTOR_SIZE - 1)), len);
+        count -= len;
+        if (count == 0)
+            return count1;
+        sector_num++;
+        buf += len;
+    }
+
+    /* read the sectors "in place" */
+    nb_sectors = count >> SECTOR_BITS;
+    if (nb_sectors > 0) {
+        if (bdrv_read(bs, sector_num, buf, nb_sectors) < 0)
+            return -EIO;
+        sector_num += nb_sectors;
+        len = nb_sectors << SECTOR_BITS;
+        buf += len;
+        count -= len;
+    }
+
+    /* add data from the last sector */
+    if (count > 0) {
+        if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
+            return -EIO;
+        memcpy(buf, tmp_buf, count);
+    }
+    return count1;
 }
 
+static int bdrv_pwrite_em(BlockDriverState *bs, int64_t offset, 
+                          const uint8_t *buf, int count1)
+{
+    uint8_t tmp_buf[SECTOR_SIZE];
+    int len, nb_sectors, count;
+    int64_t sector_num;
+
+    count = count1;
+    /* first write to align to sector start */
+    len = (SECTOR_SIZE - offset) & (SECTOR_SIZE - 1);
+    if (len > count)
+        len = count;
+    sector_num = offset >> SECTOR_BITS;
+    if (len > 0) {
+        if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
+            return -EIO;
+        memcpy(tmp_buf + (offset & (SECTOR_SIZE - 1)), buf, len);
+        if (bdrv_write(bs, sector_num, tmp_buf, 1) < 0)
+            return -EIO;
+        count -= len;
+        if (count == 0)
+            return count1;
+        sector_num++;
+        buf += len;
+    }
+
+    /* write the sectors "in place" */
+    nb_sectors = count >> SECTOR_BITS;
+    if (nb_sectors > 0) {
+        if (bdrv_write(bs, sector_num, buf, nb_sectors) < 0)
+            return -EIO;
+        sector_num += nb_sectors;
+        len = nb_sectors << SECTOR_BITS;
+        buf += len;
+        count -= len;
+    }
+
+    /* add data from the last sector */
+    if (count > 0) {
+        if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
+            return -EIO;
+        memcpy(tmp_buf, buf, count);
+        if (bdrv_write(bs, sector_num, tmp_buf, 1) < 0)
+            return -EIO;
+    }
+    return count1;
+}
+
+/**
+ * Read with byte offsets (needed only for file protocols) 
+ */
+int bdrv_pread(BlockDriverState *bs, int64_t offset, 
+               void *buf1, int count1)
+{
+    BlockDriver *drv = bs->drv;
+
+    if (!drv)
+        return -ENOMEDIUM;
+    if (!drv->bdrv_pread)
+        return bdrv_pread_em(bs, offset, buf1, count1);
+    return drv->bdrv_pread(bs, offset, buf1, count1);
+}
+
+/** 
+ * Write with byte offsets (needed only for file protocols) 
+ */
+int bdrv_pwrite(BlockDriverState *bs, int64_t offset, 
+                const void *buf1, int count1)
+{
+    BlockDriver *drv = bs->drv;
+
+    if (!drv)
+        return -ENOMEDIUM;
+    if (!drv->bdrv_pwrite)
+        return bdrv_pwrite_em(bs, offset, buf1, count1);
+    return drv->bdrv_pwrite(bs, offset, buf1, count1);
+}
+
+/**
+ * Truncate file to 'offset' bytes (needed only for file protocols)
+ */
+int bdrv_truncate(BlockDriverState *bs, int64_t offset)
+{
+    BlockDriver *drv = bs->drv;
+    if (!drv)
+        return -ENOMEDIUM;
+    if (!drv->bdrv_truncate)
+        return -ENOTSUP;
+    return drv->bdrv_truncate(bs, offset);
+}
+
+/**
+ * Length of a file in bytes. Return < 0 if error or unknown.
+ */
+int64_t bdrv_getlength(BlockDriverState *bs)
+{
+    BlockDriver *drv = bs->drv;
+    if (!drv)
+        return -ENOMEDIUM;
+    if (!drv->bdrv_getlength) {
+        /* legacy mode */
+        return bs->total_sectors * SECTOR_SIZE;
+    }
+    return drv->bdrv_getlength(bs);
+}
+
+/* return 0 as number of sectors if no device present or error */
 void bdrv_get_geometry(BlockDriverState *bs, int64_t *nb_sectors_ptr)
 {
-    *nb_sectors_ptr = bs->total_sectors;
+    int64_t length;
+    length = bdrv_getlength(bs);
+    if (length < 0)
+        length = 0;
+    else
+        length = length >> SECTOR_BITS;
+    *nb_sectors_ptr = length;
 }
 
 /* force a given boot sector. */
@@ -531,21 +782,7 @@ int bdrv_is_read_only(BlockDriverState *bs)
     return bs->read_only;
 }
 
-int bdrv_is_inserted(BlockDriverState *bs)
-{
-    return bs->inserted;
-}
-
-int bdrv_is_locked(BlockDriverState *bs)
-{
-    return bs->locked;
-}
-
-void bdrv_set_locked(BlockDriverState *bs, int locked)
-{
-    bs->locked = locked;
-}
-
+/* XXX: no longer used */
 void bdrv_set_change_cb(BlockDriverState *bs, 
                         void (*change_cb)(void *opaque), void *opaque)
 {
@@ -577,7 +814,7 @@ int bdrv_set_key(BlockDriverState *bs, const char *key)
 
 void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size)
 {
-    if (!bs->inserted || !bs->drv) {
+    if (!bs->drv) {
         buf[0] = '\0';
     } else {
         pstrcpy(buf, buf_size, bs->drv->format_name);
@@ -649,10 +886,13 @@ void bdrv_info(void)
         if (bs->removable) {
             term_printf(" locked=%d", bs->locked);
         }
-        if (bs->inserted) {
-            term_printf(" file=%s", bs->filename);
-            if (bs->backing_file[0] != '\0')
-                term_printf(" backing_file=%s", bs->backing_file);
+        if (bs->drv) {
+            term_printf(" file=");
+           term_print_filename(bs->filename);
+            if (bs->backing_file[0] != '\0') {
+                term_printf(" backing_file=");
+               term_print_filename(bs->backing_file);
+           }
             term_printf(" ro=%d", bs->read_only);
             term_printf(" drv=%s", bs->drv->format_name);
             if (bs->encrypted)
@@ -664,192 +904,337 @@ void bdrv_info(void)
     }
 }
 
+void bdrv_get_backing_filename(BlockDriverState *bs, 
+                               char *filename, int filename_size)
+{
+    if (!bs->backing_hd) {
+        pstrcpy(filename, filename_size, "");
+    } else {
+        pstrcpy(filename, filename_size, bs->backing_file);
+    }
+}
+
+int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num, 
+                          const uint8_t *buf, int nb_sectors)
+{
+    BlockDriver *drv = bs->drv;
+    if (!drv)
+        return -ENOMEDIUM;
+    if (!drv->bdrv_write_compressed)
+        return -ENOTSUP;
+    return drv->bdrv_write_compressed(bs, sector_num, buf, nb_sectors);
+}
+    
+int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
+{
+    BlockDriver *drv = bs->drv;
+    if (!drv)
+        return -ENOMEDIUM;
+    if (!drv->bdrv_get_info)
+        return -ENOTSUP;
+    memset(bdi, 0, sizeof(*bdi));
+    return drv->bdrv_get_info(bs, bdi);
+}
+
 /**************************************************************/
-/* RAW block driver */
+/* handling of snapshots */
 
-typedef struct BDRVRawState {
-    int fd;
-} BDRVRawState;
+int bdrv_snapshot_create(BlockDriverState *bs, 
+                         QEMUSnapshotInfo *sn_info)
+{
+    BlockDriver *drv = bs->drv;
+    if (!drv)
+        return -ENOMEDIUM;
+    if (!drv->bdrv_snapshot_create)
+        return -ENOTSUP;
+    return drv->bdrv_snapshot_create(bs, sn_info);
+}
 
-static int raw_probe(const uint8_t *buf, int buf_size, const char *filename)
+int bdrv_snapshot_goto(BlockDriverState *bs, 
+                       const char *snapshot_id)
 {
-    return 1; /* maybe */
+    BlockDriver *drv = bs->drv;
+    if (!drv)
+        return -ENOMEDIUM;
+    if (!drv->bdrv_snapshot_goto)
+        return -ENOTSUP;
+    return drv->bdrv_snapshot_goto(bs, snapshot_id);
 }
 
-static int raw_open(BlockDriverState *bs, const char *filename)
+int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id)
 {
-    BDRVRawState *s = bs->opaque;
-    int fd;
-    int64_t size;
-#ifdef _BSD
-    struct stat sb;
-#endif
-#ifdef __sun__
-    struct dk_minfo minfo;
-    int rv;
-#endif
+    BlockDriver *drv = bs->drv;
+    if (!drv)
+        return -ENOMEDIUM;
+    if (!drv->bdrv_snapshot_delete)
+        return -ENOTSUP;
+    return drv->bdrv_snapshot_delete(bs, snapshot_id);
+}
 
-    fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
-    if (fd < 0) {
-        fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
-        if (fd < 0)
-            return -1;
-        bs->read_only = 1;
+int bdrv_snapshot_list(BlockDriverState *bs, 
+                       QEMUSnapshotInfo **psn_info)
+{
+    BlockDriver *drv = bs->drv;
+    if (!drv)
+        return -ENOMEDIUM;
+    if (!drv->bdrv_snapshot_list)
+        return -ENOTSUP;
+    return drv->bdrv_snapshot_list(bs, psn_info);
+}
+
+#define NB_SUFFIXES 4
+
+char *get_human_readable_size(char *buf, int buf_size, int64_t size)
+{
+    static const char suffixes[NB_SUFFIXES] = "KMGT";
+    int64_t base;
+    int i;
+
+    if (size <= 999) {
+        snprintf(buf, buf_size, "%" PRId64, size);
+    } else {
+        base = 1024;
+        for(i = 0; i < NB_SUFFIXES; i++) {
+            if (size < (10 * base)) {
+                snprintf(buf, buf_size, "%0.1f%c", 
+                         (double)size / base,
+                         suffixes[i]);
+                break;
+            } else if (size < (1000 * base) || i == (NB_SUFFIXES - 1)) {
+                snprintf(buf, buf_size, "%" PRId64 "%c", 
+                         ((size + (base >> 1)) / base),
+                         suffixes[i]);
+                break;
+            }
+            base = base * 1024;
+        }
     }
-#ifdef _BSD
-    if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) {
-#ifdef DIOCGMEDIASIZE
-       if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size))
-#endif
-#ifdef CONFIG_COCOA
-        size = LONG_LONG_MAX;
+    return buf;
+}
+
+char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn)
+{
+    char buf1[128], date_buf[128], clock_buf[128];
+#ifdef _WIN32
+    struct tm *ptm;
 #else
-        size = lseek(fd, 0LL, SEEK_END);
-#endif
-    } else
-#endif
-#ifdef __sun__
-    /*
-     * use the DKIOCGMEDIAINFO ioctl to read the size.
-     */
-    rv = ioctl ( fd, DKIOCGMEDIAINFO, &minfo );
-    if ( rv != -1 ) {
-        size = minfo.dki_lbsize * minfo.dki_capacity;
-    } else /* there are reports that lseek on some devices
-              fails, but irc discussion said that contingency
-              on contingency was overkill */
+    struct tm tm;
 #endif
-    {
-        size = lseek(fd, 0, SEEK_END);
-    }
+    time_t ti;
+    int64_t secs;
+
+    if (!sn) {
+        snprintf(buf, buf_size, 
+                 "%-10s%-20s%7s%20s%15s", 
+                 "ID", "TAG", "VM SIZE", "DATE", "VM CLOCK");
+    } else {
+        ti = sn->date_sec;
 #ifdef _WIN32
-    /* On Windows hosts it can happen that we're unable to get file size
-       for CD-ROM raw device (it's inherent limitation of the CDFS driver). */
-    if (size == -1)
-        size = LONG_LONG_MAX;
+        ptm = localtime(&ti);
+        strftime(date_buf, sizeof(date_buf),
+                 "%Y-%m-%d %H:%M:%S", ptm);
+#else
+        localtime_r(&ti, &tm);
+        strftime(date_buf, sizeof(date_buf),
+                 "%Y-%m-%d %H:%M:%S", &tm);
 #endif
-    bs->total_sectors = size / 512;
-    s->fd = fd;
-    return 0;
+        secs = sn->vm_clock_nsec / 1000000000;
+        snprintf(clock_buf, sizeof(clock_buf),
+                 "%02d:%02d:%02d.%03d",
+                 (int)(secs / 3600),
+                 (int)((secs / 60) % 60),
+                 (int)(secs % 60), 
+                 (int)((sn->vm_clock_nsec / 1000000) % 1000));
+        snprintf(buf, buf_size,
+                 "%-10s%-20s%7s%20s%15s", 
+                 sn->id_str, sn->name,
+                 get_human_readable_size(buf1, sizeof(buf1), sn->vm_state_size),
+                 date_buf,
+                 clock_buf);
+    }
+    return buf;
 }
 
-static int raw_read(BlockDriverState *bs, int64_t sector_num, 
-                    uint8_t *buf, int nb_sectors)
-{
-    BDRVRawState *s = bs->opaque;
-    int ret;
-    
-    lseek(s->fd, sector_num * 512, SEEK_SET);
-    ret = read(s->fd, buf, nb_sectors * 512);
-    if (ret != nb_sectors * 512) 
-        return -1;
-    return 0;
-}
 
-static int raw_write(BlockDriverState *bs, int64_t sector_num, 
-                     const uint8_t *buf, int nb_sectors)
+/**************************************************************/
+/* async I/Os */
+
+BlockDriverAIOCB *bdrv_aio_read(BlockDriverState *bs, int64_t sector_num,
+                                uint8_t *buf, int nb_sectors,
+                                BlockDriverCompletionFunc *cb, void *opaque)
 {
-    BDRVRawState *s = bs->opaque;
-    int ret;
+    BlockDriver *drv = bs->drv;
+
+    if (!drv)
+        return NULL;
     
-    lseek(s->fd, sector_num * 512, SEEK_SET);
-    ret = write(s->fd, buf, nb_sectors * 512);
-    if (ret != nb_sectors * 512) 
-        return -1;
-    return 0;
+    /* XXX: we assume that nb_sectors == 0 is suppored by the async read */
+    if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
+        memcpy(buf, bs->boot_sector_data, 512);
+        sector_num++;
+        nb_sectors--;
+        buf += 512;
+    }
+
+    return drv->bdrv_aio_read(bs, sector_num, buf, nb_sectors, cb, opaque);
 }
 
-static void raw_close(BlockDriverState *bs)
+BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, int64_t sector_num,
+                                 const uint8_t *buf, int nb_sectors,
+                                 BlockDriverCompletionFunc *cb, void *opaque)
 {
-    BDRVRawState *s = bs->opaque;
-    bs->total_sectors = 0;
-    close(s->fd);
-}
+    BlockDriver *drv = bs->drv;
 
-#ifdef _WIN32
-#include <windows.h>
-#include <winioctl.h>
+    if (!drv)
+        return NULL;
+    if (bs->read_only)
+        return NULL;
+    if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
+        memcpy(bs->boot_sector_data, buf, 512);   
+    }
+
+    return drv->bdrv_aio_write(bs, sector_num, buf, nb_sectors, cb, opaque);
+}
 
-int qemu_ftruncate64(int fd, int64_t length)
+void bdrv_aio_cancel(BlockDriverAIOCB *acb)
 {
-    LARGE_INTEGER li;
-    LONG high;
-    HANDLE h;
-    BOOL res;
+    BlockDriver *drv = acb->bs->drv;
 
-    if ((GetVersion() & 0x80000000UL) && (length >> 32) != 0)
-       return -1;
+    drv->bdrv_aio_cancel(acb);
+}
 
-    h = (HANDLE)_get_osfhandle(fd);
 
-    /* get current position, ftruncate do not change position */
-    li.HighPart = 0;
-    li.LowPart = SetFilePointer (h, 0, &li.HighPart, FILE_CURRENT);
-    if (li.LowPart == 0xffffffffUL && GetLastError() != NO_ERROR)
-       return -1;
+/**************************************************************/
+/* async block device emulation */
 
-    high = length >> 32;
-    if (!SetFilePointer(h, (DWORD) length, &high, FILE_BEGIN))
-       return -1;
-    res = SetEndOfFile(h);
+#ifdef QEMU_TOOL
+static BlockDriverAIOCB *bdrv_aio_read_em(BlockDriverState *bs,
+        int64_t sector_num, uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque)
+{
+    int ret;
+    ret = bdrv_read(bs, sector_num, buf, nb_sectors);
+    cb(opaque, ret);
+    return NULL;
+}
 
-    /* back to old position */
-    SetFilePointer(h, li.LowPart, &li.HighPart, FILE_BEGIN);
-    return res ? 0 : -1;
+static BlockDriverAIOCB *bdrv_aio_write_em(BlockDriverState *bs,
+        int64_t sector_num, const uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque)
+{
+    int ret;
+    ret = bdrv_write(bs, sector_num, buf, nb_sectors);
+    cb(opaque, ret);
+    return NULL;
 }
 
-static int set_sparse(int fd)
+static void bdrv_aio_cancel_em(BlockDriverAIOCB *acb)
 {
-    DWORD returned;
-    return (int) DeviceIoControl((HANDLE)_get_osfhandle(fd), FSCTL_SET_SPARSE,
-                                NULL, 0, NULL, 0, &returned, NULL);
 }
 #else
-static inline int set_sparse(int fd)
+static void bdrv_aio_bh_cb(void *opaque)
 {
-    return 1;
+    BlockDriverAIOCBSync *acb = opaque;
+    acb->common.cb(acb->common.opaque, acb->ret);
+    qemu_aio_release(acb);
 }
-#endif
 
-static int raw_create(const char *filename, int64_t total_size,
-                      const char *backing_file, int flags)
+static BlockDriverAIOCB *bdrv_aio_read_em(BlockDriverState *bs,
+        int64_t sector_num, uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque)
 {
-    int fd;
+    BlockDriverAIOCBSync *acb;
+    int ret;
 
-    if (flags || backing_file)
-        return -ENOTSUP;
+    acb = qemu_aio_get(bs, cb, opaque);
+    if (!acb->bh)
+        acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
+    ret = bdrv_read(bs, sector_num, buf, nb_sectors);
+    acb->ret = ret;
+    qemu_bh_schedule(acb->bh);
+    return &acb->common;
+}
 
-    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, 
-              0644);
-    if (fd < 0)
-        return -EIO;
-    set_sparse(fd);
-    ftruncate(fd, total_size * 512);
-    close(fd);
-    return 0;
+static BlockDriverAIOCB *bdrv_aio_write_em(BlockDriverState *bs,
+        int64_t sector_num, const uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque)
+{
+    BlockDriverAIOCBSync *acb;
+    int ret;
+
+    acb = qemu_aio_get(bs, cb, opaque);
+    if (!acb->bh)
+        acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
+    ret = bdrv_write(bs, sector_num, buf, nb_sectors);
+    acb->ret = ret;
+    qemu_bh_schedule(acb->bh);
+    return &acb->common;
 }
 
-static void raw_flush(BlockDriverState *bs)
+static void bdrv_aio_cancel_em(BlockDriverAIOCB *blockacb)
 {
-    BDRVRawState *s = bs->opaque;
-    fsync(s->fd);
+    BlockDriverAIOCBSync *acb = (BlockDriverAIOCBSync *)blockacb;
+    qemu_bh_cancel(acb->bh);
+    qemu_aio_release(acb);
 }
+#endif /* !QEMU_TOOL */
+
+/**************************************************************/
+/* sync block device emulation */
 
-BlockDriver bdrv_raw = {
-    "raw",
-    sizeof(BDRVRawState),
-    raw_probe,
-    raw_open,
-    raw_read,
-    raw_write,
-    raw_close,
-    raw_create,
-    raw_flush,
-};
+static void bdrv_rw_em_cb(void *opaque, int ret)
+{
+    *(int *)opaque = ret;
+}
+
+#define NOT_DONE 0x7fffffff
+
+static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num, 
+                        uint8_t *buf, int nb_sectors)
+{
+    int async_ret;
+    BlockDriverAIOCB *acb;
+
+    async_ret = NOT_DONE;
+    qemu_aio_wait_start();
+    acb = bdrv_aio_read(bs, sector_num, buf, nb_sectors, 
+                        bdrv_rw_em_cb, &async_ret);
+    if (acb == NULL) {
+        qemu_aio_wait_end();
+        return -1;
+    }
+    while (async_ret == NOT_DONE) {
+        qemu_aio_wait();
+    }
+    qemu_aio_wait_end();
+    return async_ret;
+}
+
+static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
+                         const uint8_t *buf, int nb_sectors)
+{
+    int async_ret;
+    BlockDriverAIOCB *acb;
+
+    async_ret = NOT_DONE;
+    qemu_aio_wait_start();
+    acb = bdrv_aio_write(bs, sector_num, buf, nb_sectors, 
+                         bdrv_rw_em_cb, &async_ret);
+    if (acb == NULL) {
+        qemu_aio_wait_end();
+        return -1;
+    }
+    while (async_ret == NOT_DONE) {
+        qemu_aio_wait();
+    }
+    qemu_aio_wait_end();
+    return async_ret;
+}
 
 void bdrv_init(void)
 {
     bdrv_register(&bdrv_raw);
+    bdrv_register(&bdrv_host_device);
 #ifndef _WIN32
     bdrv_register(&bdrv_cow);
 #endif
@@ -860,4 +1245,109 @@ void bdrv_init(void)
     bdrv_register(&bdrv_bochs);
     bdrv_register(&bdrv_vpc);
     bdrv_register(&bdrv_vvfat);
+    bdrv_register(&bdrv_qcow2);
+}
+
+void *qemu_aio_get(BlockDriverState *bs, BlockDriverCompletionFunc *cb,
+                   void *opaque)
+{
+    BlockDriver *drv;
+    BlockDriverAIOCB *acb;
+
+    drv = bs->drv;
+    if (drv->free_aiocb) {
+        acb = drv->free_aiocb;
+        drv->free_aiocb = acb->next;
+    } else {
+        acb = qemu_mallocz(drv->aiocb_size);
+        if (!acb)
+            return NULL;
+    }
+    acb->bs = bs;
+    acb->cb = cb;
+    acb->opaque = opaque;
+    return acb;
+}
+
+void qemu_aio_release(void *p)
+{
+    BlockDriverAIOCB *acb = p;
+    BlockDriver *drv = acb->bs->drv;
+    acb->next = drv->free_aiocb;
+    drv->free_aiocb = acb;
+}
+
+/**************************************************************/
+/* removable device support */
+
+/**
+ * Return TRUE if the media is present
+ */
+int bdrv_is_inserted(BlockDriverState *bs)
+{
+    BlockDriver *drv = bs->drv;
+    int ret;
+    if (!drv)
+        return 0;
+    if (!drv->bdrv_is_inserted)
+        return 1;
+    ret = drv->bdrv_is_inserted(bs);
+    return ret;
+}
+
+/**
+ * Return TRUE if the media changed since the last call to this
+ * function. It is currently only used for floppy disks 
+ */
+int bdrv_media_changed(BlockDriverState *bs)
+{
+    BlockDriver *drv = bs->drv;
+    int ret;
+
+    if (!drv || !drv->bdrv_media_changed)
+        ret = -ENOTSUP;
+    else
+        ret = drv->bdrv_media_changed(bs);
+    if (ret == -ENOTSUP)
+        ret = bs->media_changed;
+    bs->media_changed = 0;
+    return ret;
+}
+
+/**
+ * If eject_flag is TRUE, eject the media. Otherwise, close the tray
+ */
+void bdrv_eject(BlockDriverState *bs, int eject_flag)
+{
+    BlockDriver *drv = bs->drv;
+    int ret;
+
+    if (!drv || !drv->bdrv_eject) {
+        ret = -ENOTSUP;
+    } else {
+        ret = drv->bdrv_eject(bs, eject_flag);
+    }
+    if (ret == -ENOTSUP) {
+        if (eject_flag)
+            bdrv_close(bs);
+    }
+}
+
+int bdrv_is_locked(BlockDriverState *bs)
+{
+    return bs->locked;
+}
+
+/**
+ * Lock or unlock the media (if it is locked, the user won't be able
+ * to eject it manually).
+ */
+void bdrv_set_locked(BlockDriverState *bs, int locked)
+{
+    BlockDriver *drv = bs->drv;
+
+    bs->locked = locked;
+    if (drv && drv->bdrv_set_locked) {
+        drv->bdrv_set_locked(bs, locked);
+    }
 }
index c2a2e30a9f9cd30ec88afe1c43df4de4e35d416e..25f6717b5c53a882413fe6c1ca79b0eefd0ebef2 100644 (file)
@@ -28,7 +28,7 @@ struct BlockDriver {
     const char *format_name;
     int instance_size;
     int (*bdrv_probe)(const uint8_t *buf, int buf_size, const char *filename);
-    int (*bdrv_open)(BlockDriverState *bs, const char *filename);
+    int (*bdrv_open)(BlockDriverState *bs, const char *filename, int flags);
     int (*bdrv_read)(BlockDriverState *bs, int64_t sector_num, 
                      uint8_t *buf, int nb_sectors);
     int (*bdrv_write)(BlockDriverState *bs, int64_t sector_num, 
@@ -41,13 +41,49 @@ struct BlockDriver {
                              int nb_sectors, int *pnum);
     int (*bdrv_set_key)(BlockDriverState *bs, const char *key);
     int (*bdrv_make_empty)(BlockDriverState *bs);
+    /* aio */
+    BlockDriverAIOCB *(*bdrv_aio_read)(BlockDriverState *bs,
+        int64_t sector_num, uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque);
+    BlockDriverAIOCB *(*bdrv_aio_write)(BlockDriverState *bs,
+        int64_t sector_num, const uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque);
+    void (*bdrv_aio_cancel)(BlockDriverAIOCB *acb);
+    int aiocb_size;
+
+    const char *protocol_name;
+    int (*bdrv_pread)(BlockDriverState *bs, int64_t offset, 
+                      uint8_t *buf, int count);
+    int (*bdrv_pwrite)(BlockDriverState *bs, int64_t offset, 
+                       const uint8_t *buf, int count);
+    int (*bdrv_truncate)(BlockDriverState *bs, int64_t offset);
+    int64_t (*bdrv_getlength)(BlockDriverState *bs);
+    int (*bdrv_write_compressed)(BlockDriverState *bs, int64_t sector_num, 
+                                 const uint8_t *buf, int nb_sectors);
+
+    int (*bdrv_snapshot_create)(BlockDriverState *bs, 
+                                QEMUSnapshotInfo *sn_info);
+    int (*bdrv_snapshot_goto)(BlockDriverState *bs, 
+                              const char *snapshot_id);
+    int (*bdrv_snapshot_delete)(BlockDriverState *bs, const char *snapshot_id);
+    int (*bdrv_snapshot_list)(BlockDriverState *bs, 
+                              QEMUSnapshotInfo **psn_info);
+    int (*bdrv_get_info)(BlockDriverState *bs, BlockDriverInfo *bdi);
+
+    /* removable device specific */
+    int (*bdrv_is_inserted)(BlockDriverState *bs);
+    int (*bdrv_media_changed)(BlockDriverState *bs);
+    int (*bdrv_eject)(BlockDriverState *bs, int eject_flag);
+    int (*bdrv_set_locked)(BlockDriverState *bs, int locked);
+    
+    BlockDriverAIOCB *free_aiocb;
     struct BlockDriver *next;
 };
 
 struct BlockDriverState {
-    int64_t total_sectors;
+    int64_t total_sectors; /* if we are reading a disk image, give its
+                              size in sectors */
     int read_only; /* if true, the media is read only */
-    int inserted; /* if true, the media is present */
     int removable; /* if true, the media can be removed */
     int locked;    /* if true, the media cannot temporarily be ejected */
     int encrypted; /* if true, the media is encrypted */
@@ -55,7 +91,7 @@ struct BlockDriverState {
     void (*change_cb)(void *opaque);
     void *change_opaque;
 
-    BlockDriver *drv;
+    BlockDriver *drv; /* NULL means no media */
     void *opaque;
 
     int boot_sector_enabled;
@@ -65,8 +101,12 @@ struct BlockDriverState {
     char backing_file[1024]; /* if non zero, the image is a diff of
                                 this file image */
     int is_temporary;
-    
+    int media_changed;
+
     BlockDriverState *backing_hd;
+    /* async read/write emulation */
+
+    void *sync_aiocb;
     
     /* NOTE: the following infos are only hints for real hardware
        drivers. They are not used by the block driver */
@@ -76,6 +116,17 @@ struct BlockDriverState {
     BlockDriverState *next;
 };
 
+struct BlockDriverAIOCB {
+    BlockDriverState *bs;
+    BlockDriverCompletionFunc *cb;
+    void *opaque;
+    BlockDriverAIOCB *next;
+};
+
 void get_tmp_filename(char *filename, int size);
 
+void *qemu_aio_get(BlockDriverState *bs, BlockDriverCompletionFunc *cb,
+                   void *opaque);
+void qemu_aio_release(void *p);
+
 #endif /* BLOCK_INT_H */
diff --git a/tools/ioemu/check_ops.sh b/tools/ioemu/check_ops.sh
new file mode 100755 (executable)
index 0000000..b1f2f85
--- /dev/null
@@ -0,0 +1,47 @@
+#! /bin/sh
+# Script to check for duplicate function prologues in op.o
+# Typically this indicates missing FORCE_RET();
+# This script does not detect other errors that may be present.
+
+# Usage: check_ops.sh [-m machine] [op.o]
+#   machine and op.o are guessed if not specified.
+
+if [ "x$1" = "x-m" ]; then
+  machine=$2
+  shift 2
+else
+  machine=`uname -m`
+fi
+if [ -z "$1" ]; then
+  for f in `find . -name op.o`; do
+    /bin/sh "$0" -m $machine $f
+  done
+  exit 0
+fi
+
+case $machine in
+  i?86)
+    ret='\tret'
+    ;;
+  x86_64)
+    ret='\tretq'
+    ;;
+  arm)
+    ret='\tldm.*pc'
+    ;;
+  ppc* | powerpc*)
+    ret='\tblr'
+    ;;
+  mips*)
+    ret='\tjr.*ra'
+    ;;
+  *)
+    echo "Unknown machine `uname -m`"
+    ;;
+esac
+echo $1
+# op_exit_tb causes false positives on some hosts.
+${CROSS}objdump -dr $1  | \
+  sed -e '/>:$\|'"$ret"'/!d' -e 's/.*<\(.*\)>:/~\1:/' -e 's/.*'"$ret"'.*/!/' | \
+  sed -e ':1;N;s/\n//;t1' | sed -e 's/~/\n/g' | grep -v '^op_exit_tb' | \
+  grep '^op_.*!!'
index 98e1d03bfdcb16988d2eb96c51ee08055514a1fa..6de198fd3d95953557c0c41bb4afa701e78cd216 100755 (executable)
@@ -22,6 +22,8 @@ static="no"
 libdir="lib"
 cross_prefix=""
 cc="gcc"
+gcc3_search="yes"
+gcc3_list="gcc-3.4 gcc34 gcc-3.3 gcc33 gcc-3.2 gcc32"
 host_cc="gcc"
 ar="ar"
 make="make"
@@ -89,14 +91,13 @@ bsd="no"
 linux="no"
 kqemu="no"
 profiler="no"
-kernel_path=""
 cocoa="no"
 check_gfx="yes"
 check_gcc="no"
 softmmu="yes"
-user="no"
+linux_user="no"
+darwin_user="no"
 build_docs="no"
-build_acpi_tables="no"
 uname_release=""
 
 # OS specific
@@ -104,7 +105,7 @@ targetos=`uname -s`
 case $targetos in
 CYGWIN*)
 mingw32="yes"
-CFLAGS="-O2 -mno-cygwin"
+OS_CFLAGS="-mno-cygwin"
 ;;
 MINGW32*)
 mingw32="yes"
@@ -127,6 +128,10 @@ oss="yes"
 Darwin)
 bsd="yes"
 darwin="yes"
+darwin_user="yes"
+cocoa="yes"
+coreaudio="yes"
+OS_CFLAGS="-mdynamic-no-pic"
 ;;
 SunOS)
 solaris="yes"
@@ -134,7 +139,7 @@ solaris="yes"
 *)
 oss="yes"
 linux="yes"
-user="yes"
+linux_user="yes"
 if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then
     kqemu="yes"
 fi
@@ -151,6 +156,11 @@ if [ "$solaris" = "yes" ] ; then
     make="gmake"
     install="ginstall"
     solarisrev=`uname -r | cut -f2 -d.`
+    if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then
+        if test "$solarisrev" -gt 10 ; then
+            kqemu="yes"
+        fi
+    fi
 fi
 
 # find source path
@@ -181,6 +191,7 @@ for opt do
   --cross-prefix=*) cross_prefix="$optarg"
   ;;
   --cc=*) cc="$optarg"
+  gcc3_search="no"
   ;;
   --host-cc=*) host_cc="$optarg"
   ;;
@@ -224,8 +235,6 @@ for opt do
   ;;
   --enable-profiler) profiler="yes"
   ;;
-  --kernel-path=*) kernel_path="$optarg"
-  ;;
   --enable-cocoa) cocoa="yes" ; coreaudio="yes" ; sdl="no"
   ;;
   --disable-gcc-check) check_gcc="no"
@@ -234,21 +243,22 @@ for opt do
   ;;
   --enable-system) softmmu="yes"
   ;;
-  --disable-user) user="no"
+  --disable-linux-user) linux_user="no"
   ;;
-  --enable-user) user="yes"
+  --enable-linux-user) linux_user="yes"
   ;;
-  --enable-uname-release=*) uname_release="$optarg"
+  --disable-darwin-user) darwin_user="no"
   ;;
-  --enable-iasl) build_acpi_tables="yes"
+  --enable-darwin-user) darwin_user="yes"
+  ;;
+  --enable-uname-release=*) uname_release="$optarg"
   ;;
   esac
 done
 
-# Checking for CFLAGS
-if test -z "$CFLAGS"; then
-    CFLAGS="-O2"
-fi
+# default flags for all hosts
+CFLAGS="$CFLAGS -Wall -O2 -g -fno-strict-aliasing"
+LDFLAGS="$LDFLAGS -g"
 
 if test x"$show_help" = x"yes" ; then
 cat << EOF
@@ -266,7 +276,6 @@ echo "  --target-list=LIST       set target list [$target_list]"
 echo ""
 echo "kqemu kernel acceleration support:"
 echo "  --disable-kqemu          disable kqemu support"
-echo "  --kernel-path=PATH       set the kernel path (configure probes it)"
 echo ""
 echo "Advanced options (experts only):"
 echo "  --source-path=PATH       path of source code [$source_path]"
@@ -285,14 +294,15 @@ echo "  --enable-fmod            enable FMOD audio driver"
 echo "  --enabled-dsound         enable DirectSound audio driver"
 echo "  --enable-system          enable all system emulation targets"
 echo "  --disable-system         disable all system emulation targets"
-echo "  --enable-user            enable all linux usermode emulation targets"
-echo "  --disable-user           disable all linux usermode emulation targets"
+echo "  --enable-linux-user      enable all linux usermode emulation targets"
+echo "  --disable-linux-user     disable all linux usermode emulation targets"
+echo "  --enable-darwin-user     enable all darwin usermode emulation targets"
+echo "  --disable-darwin-user    disable all darwin usermode emulation targets"
 echo "  --fmod-lib               path to FMOD library"
 echo "  --fmod-inc               path to FMOD includes"
 echo "  --enable-uname-release=R Return R for uname -r in usermode emulation"
-echo "  --enable-iasl            compilation of ACPI tables with the IASL compiler"
 echo ""
-echo "NOTE: The object files are build at the place where configure is launched"
+echo "NOTE: The object files are built at the place where configure is launched"
 exit 1
 fi
 
@@ -321,6 +331,45 @@ if test "$mingw32" = "yes" ; then
     fi
 fi
 
+# Check for gcc4, error if pre-gcc4 
+if test "$check_gcc" = "yes" ; then
+    cat > $TMPC <<EOF
+#if __GNUC__ < 4
+#error gcc3
+#endif
+int main(){return 0;}
+EOF
+    check_cc() {
+       which "$1" >&/dev/null
+       return $?
+    }
+
+    if "$cc" -o $TMPE $TMPC 2>/dev/null ; then
+       echo "WARNING: \"$cc\" looks like gcc 4.x"
+       found_compat_cc="no"
+       if test "$gcc3_search" = "yes" ; then
+           echo "Looking for gcc 3.x"
+           for compat_cc in $gcc3_list ; do
+               if check_cc "$compat_cc" ; then
+                   echo "Found \"$compat_cc\""
+                   cc="$compat_cc"
+                   found_compat_cc="yes"
+                   break
+               fi
+           done
+           if test "$found_compat_cc" = "no" ; then
+               echo "gcc 3.x not found!"
+           fi
+       fi
+       if test "$found_compat_cc" = "no" ; then
+           echo "QEMU is known to have problems when compiled with gcc 4.x"
+           echo "It is recommended that you use gcc 3.x to build QEMU"
+           echo "To use this compiler anyway, configure with --disable-gcc-check"
+           exit 1;
+       fi
+    fi
+fi
+
 #
 # Solaris specific configure tool chain decisions
 #
@@ -368,8 +417,12 @@ if test -z "$target_list" ; then
         target_list="i386-softmmu ppc-softmmu sparc-softmmu x86_64-softmmu mips-softmmu mipsel-softmmu arm-softmmu"
     fi
 # the following are Linux specific
-    if [ "$user" = "yes" ] ; then
-        target_list="i386-user arm-user armeb-user sparc-user ppc-user mips-user mipsel-user $target_list"
+    if [ "$linux_user" = "yes" ] ; then
+        target_list="i386-linux-user arm-linux-user armeb-linux-user sparc-linux-user ppc-linux-user mips-linux-user mipsel-linux-user m68k-linux-user $target_list"
+    fi
+# the following are Darwin specific
+    if [ "$darwin_user" = "yes" ] ; then
+        target_list="i386-darwin-user ppc-darwin-user $target_list"
     fi
 # the i386-dm target
     target_list="i386-dm"
@@ -427,23 +480,6 @@ if $cc -fno-reorder-blocks -fno-optimize-sibling-calls -o $TMPO $TMPC 2> /dev/nu
    have_gcc3_options="yes"
 fi
 
-# Check for gcc4, error if pre-gcc4 
-if test "$check_gcc" = "yes" ; then
-    cat > $TMPC <<EOF
-#if __GNUC__ < 4
-#error gcc3
-#endif
-int main(){return 0;}
-EOF
-    if $cc -o $TMPO $TMPC 2>/dev/null ; then
-        echo "ERROR: \"$cc\" looks like gcc 4.x"
-        echo "QEMU is known to have problems when compiled with gcc 4.x"
-        echo "It is recommended that you use gcc 3.x to build QEMU"
-        echo "To use this compiler anyway, configure with --disable-gcc-check"
-        exit 1;
-    fi
-fi
-
 ##########################################
 # SDL probe
 
@@ -472,7 +508,9 @@ _sdlversion=`$sdl_config --version | sed 's/[^0-9]//g'`
 if test "$_sdlversion" -lt 121 ; then
 sdl_too_old=yes
 else
-sdl=yes
+ if test "$cocoa" = "no" ; then
+   sdl=yes
+ fi
 fi
 
 # static link with sdl ?
@@ -493,8 +531,34 @@ fi # static link
 fi # sdl compile test
 
 fi # cross compilation
+
+else
+ # Make sure to disable cocoa if sdl was set
+ if test "$sdl" = "yes" ; then
+   cocoa="no"
+   coreaudio="no"
+ fi
 fi # -z $sdl
 
+##########################################
+# alsa sound support libraries
+
+if test "$alsa" = "yes" ; then
+  cat > $TMPC << EOF
+#include <alsa/asoundlib.h>
+int main(void) { snd_pcm_t **handle; return snd_pcm_close(*handle); }
+EOF
+  if $cc -o $TMPE $TMPC -lasound 2> /dev/null ; then
+    :
+  else
+    echo
+    echo "Error: Could not find alsa"
+    echo "Make sure to have the alsa libs and headers installed."
+    echo
+    exit 1
+  fi
+fi
+
 # Check if tools are available to build documentation.
 if [ -x "`which texi2html`" ] && [ -x "`which pod2man`" ]; then
   build_docs="yes"
@@ -600,6 +664,7 @@ fi
 echo "HOST_CC=$host_cc" >> $config_mak
 echo "AR=$ar" >> $config_mak
 echo "STRIP=$strip -s -R .comment -R .note" >> $config_mak
+echo "OS_CFLAGS=$OS_CFLAGS" >> $config_mak
 echo "CFLAGS=$CFLAGS" >> $config_mak
 echo "LDFLAGS=$LDFLAGS" >> $config_mak
 echo "EXESUF=$EXESUF" >> $config_mak
@@ -719,9 +784,6 @@ echo "TARGET_DIRS=$target_list" >> $config_mak
 if [ "$build_docs" = "yes" ] ; then
   echo "BUILD_DOCS=yes" >> $config_mak
 fi
-if [ "$build_acpi_tables" = "yes" ] ; then
-  echo "BUILD_ACPI_TABLES=yes" >> $config_mak
-fi
 
 # XXX: suppress that
 if [ "$bsd" = "yes" ] ; then
@@ -745,6 +807,7 @@ target_bigendian="no"
 [ "$target_cpu" = "ppc64" ] && target_bigendian=yes
 [ "$target_cpu" = "mips" ] && target_bigendian=yes
 [ "$target_cpu" = "sh4eb" ] && target_bigendian=yes
+[ "$target_cpu" = "m68k" ] && target_bigendian=yes
 target_softmmu="no"
 if expr $target : '.*-softmmu' > /dev/null ; then
   target_softmmu="yes"
@@ -756,11 +819,21 @@ if expr $target : '.*-user' > /dev/null ; then
   target_user_only="yes"
 fi
 
+target_linux_user="no"
+if expr $target : '.*-linux-user' > /dev/null ; then
+  target_linux_user="yes"
+fi
+
+target_darwin_user="no"
+if expr $target : '.*-darwin-user' > /dev/null ; then
+  target_darwin_user="yes"
+fi
+
 #echo "Creating $config_mak, $config_h and $target_dir/Makefile"
 
 mkdir -p $target_dir
 mkdir -p $target_dir/fpu
-if test "$target" = "arm-user" -o "$target" = "armeb-user" ; then
+if test "$target" = "arm-linux-user" -o "$target" = "armeb-linux-user" ; then
   mkdir -p $target_dir/nwfpe
 fi
 if test "$target_user_only" = "no" ; then
@@ -840,6 +913,11 @@ elif test "$target_cpu" = "sh4" -o "$target_cpu" = "sh4eb" ; then
   echo "#define TARGET_ARCH \"sh4\"" >> $config_h
   echo "#define TARGET_SH4 1" >> $config_h
   bflt="yes"
+elif test "$target_cpu" = "m68k" ; then
+  echo "TARGET_ARCH=m68k" >> $config_mak
+  echo "#define TARGET_ARCH \"m68k\"" >> $config_h
+  echo "#define TARGET_M68K 1" >> $config_h
+  bflt="yes"
 else
   echo "Unsupported target CPU"
   exit 1
@@ -856,12 +934,19 @@ if test "$target_user_only" = "yes" ; then
   echo "CONFIG_USER_ONLY=yes" >> $config_mak
   echo "#define CONFIG_USER_ONLY 1" >> $config_h
 fi
-
+if test "$target_linux_user" = "yes" ; then
+  echo "CONFIG_LINUX_USER=yes" >> $config_mak
+  echo "#define CONFIG_LINUX_USER 1" >> $config_h
+fi
+if test "$target_darwin_user" = "yes" ; then
+  echo "CONFIG_DARWIN_USER=yes" >> $config_mak
+  echo "#define CONFIG_DARWIN_USER 1" >> $config_h
+fi
 if expr $target : '.*-dm' > /dev/null ; then
   echo "#define CONFIG_DM 1" >> $config_h
 fi
 
-if test "$target_cpu" = "arm" -o "$target_cpu" = "armeb" -o "$target_cpu" = "sparc" -o "$target_cpu" = "sparc64"; then
+if test "$target_cpu" = "arm" -o "$target_cpu" = "armeb" -o "$target_cpu" = "sparc" -o "$target_cpu" = "sparc64" -o "$target_cpu" = "m68k"; then
   echo "CONFIG_SOFTFLOAT=yes" >> $config_mak
   echo "#define CONFIG_SOFTFLOAT 1" >> $config_h
 fi
index dfa93bcef613c4371591fbae5cf9435fbf5c5b6f..634e3d85d093f6dbf95a4824b87f38b78f676b41 100644 (file)
@@ -121,6 +121,7 @@ struct TextConsole {
     int total_height;
     int backscroll_height;
     int x, y;
+    int x_saved, y_saved;
     int y_displayed;
     int y_base;
     TextAttributes t_attrib_default; /* default text attributes */
@@ -131,10 +132,7 @@ struct TextConsole {
     int esc_params[MAX_ESC_PARAMS];
     int nb_esc_params;
 
-    /* kbd read handler */
-    IOCanRWHandler *fd_can_read; 
-    IOReadHandler *fd_read;
-    void *fd_opaque;
+    CharDriverState *chr;
     /* fifo for key pressed */
     QEMUFIFO out_fifo;
     uint8_t out_fifo_buf[16];
@@ -147,7 +145,7 @@ static int nb_consoles = 0;
 
 void vga_hw_update(void)
 {
-    if (active_console->hw_update)
+    if (active_console && active_console->hw_update)
         active_console->hw_update(active_console->hw);
 }
 
@@ -659,10 +657,6 @@ static void console_handle_escape(TextConsole *s)
 {
     int i;
 
-    if (s->nb_esc_params == 0) { /* ESC[m sets all attributes to default */
-        s->t_attrib = s->t_attrib_default;
-        return;
-    }
     for (i=0; i<s->nb_esc_params; i++) {
         switch (s->esc_params[i]) {
             case 0: /* reset all console attributes to default */
@@ -752,10 +746,21 @@ static void console_handle_escape(TextConsole *s)
     }
 }
 
+static void console_clear_xy(TextConsole *s, int x, int y)
+{
+    int y1 = (s->y_base + y) % s->total_height;
+    TextCell *c = &s->cells[y1 * s->width + x];
+    c->ch = ' ';
+    c->t_attrib = s->t_attrib_default;
+    c++;
+    update_xy(s, x, y);
+}
+
 static void console_putchar(TextConsole *s, int ch)
 {
     TextCell *c;
-    int y1, i, x;
+    int y1, i;
+    int x, y;
 
     switch(s->state) {
     case TTY_STATE_NORM:
@@ -781,20 +786,31 @@ static void console_putchar(TextConsole *s, int ch)
         case '\a':  /* alert aka. bell */
             /* TODO: has to be implemented */
             break;
+        case 14:
+            /* SI (shift in), character set 0 (ignored) */
+            break;
+        case 15:
+            /* SO (shift out), character set 1 (ignored) */
+            break;
         case 27:    /* esc (introducing an escape sequence) */
             s->state = TTY_STATE_ESC;
             break;
         default:
+            if (s->x >= s->width - 1) {
+                break;
+            }
             y1 = (s->y_base + s->y) % s->total_height;
             c = &s->cells[y1 * s->width + s->x];
             c->ch = ch;
             c->t_attrib = s->t_attrib;
             update_xy(s, s->x, s->y);
             s->x++;
+#if 0 /* line wrap disabled */
             if (s->x >= s->width) {
                 s->x = 0;
                 console_put_lf(s);
             }
+#endif
             break;
         }
         break;
@@ -818,32 +834,150 @@ static void console_putchar(TextConsole *s, int ch)
             s->nb_esc_params++;
             if (ch == ';')
                 break;
+#ifdef DEBUG_CONSOLE
+            fprintf(stderr, "escape sequence CSI%d;%d%c, %d parameters\n",
+                    s->esc_params[0], s->esc_params[1], ch, s->nb_esc_params);
+#endif
             s->state = TTY_STATE_NORM;
             switch(ch) {
-            case 'D':
-                if (s->x > 0)
-                    s->x--;
+            case 'A':
+                /* move cursor up */
+                if (s->esc_params[0] == 0) {
+                    s->esc_params[0] = 1;
+                }
+                s->y -= s->esc_params[0];
+                if (s->y < 0) {
+                    s->y = 0;
+                }
+                break;
+            case 'B':
+                /* move cursor down */
+                if (s->esc_params[0] == 0) {
+                    s->esc_params[0] = 1;
+                }
+                s->y += s->esc_params[0];
+                if (s->y >= s->height) {
+                    s->y = s->height - 1;
+                }
                 break;
             case 'C':
-                if (s->x < (s->width - 1))
-                    s->x++;
+                /* move cursor right */
+                if (s->esc_params[0] == 0) {
+                    s->esc_params[0] = 1;
+                }
+                s->x += s->esc_params[0];
+                if (s->x >= s->width) {
+                    s->x = s->width - 1;
+                }
                 break;
+            case 'D':
+                /* move cursor left */
+                if (s->esc_params[0] == 0) {
+                    s->esc_params[0] = 1;
+                }
+                s->x -= s->esc_params[0];
+                if (s->x < 0) {
+                    s->x = 0;
+                }
+                break;
+            case 'G':
+                /* move cursor to column */
+                s->x = s->esc_params[0] - 1;
+                if (s->x < 0) {
+                    s->x = 0;
+                }
+                break;
+            case 'f':
+            case 'H':
+                /* move cursor to row, column */
+                s->x = s->esc_params[1] - 1;
+                if (s->x < 0) {
+                    s->x = 0;
+                }
+                s->y = s->esc_params[0] - 1;
+                if (s->y < 0) {
+                    s->y = 0;
+                }
+                break;
+            case 'J':
+                switch (s->esc_params[0]) {
+                case 0:
+                    /* clear to end of screen */
+                    for (y = s->y; y < s->height; y++) {
+                        for (x = 0; x < s->width; x++) {
+                            if (y == s->y && x < s->x) {
+                                continue;
+                            }
+                            console_clear_xy(s, x, y);
+                        }
+                    }
+                    break;
+                case 1:
+                    /* clear from beginning of screen */
+                    for (y = 0; y <= s->y; y++) {
+                        for (x = 0; x < s->width; x++) {
+                            if (y == s->y && x > s->x) {
+                                break;
+                            }
+                            console_clear_xy(s, x, y);
+                        }
+                    }
+                    break;
+                case 2:
+                    /* clear entire screen */
+                    for (y = 0; y <= s->height; y++) {
+                        for (x = 0; x < s->width; x++) {
+                            console_clear_xy(s, x, y);
+                        }
+                    }
+                break;
+                }
             case 'K':
+                switch (s->esc_params[0]) {
+                case 0:
                 /* clear to eol */
-                y1 = (s->y_base + s->y) % s->total_height;
                 for(x = s->x; x < s->width; x++) {
-                    c = &s->cells[y1 * s->width + x];
-                    c->ch = ' ';
-                    c->t_attrib = s->t_attrib_default;
-                    c++;
-                    update_xy(s, x, s->y);
+                        console_clear_xy(s, x, s->y);
                 }
                 break;
-            default:
+                case 1:
+                    /* clear from beginning of line */
+                    for (x = 0; x <= s->x; x++) {
+                        console_clear_xy(s, x, s->y);
+                    }
+                    break;
+                case 2:
+                    /* clear entire line */
+                    for(x = 0; x < s->width; x++) {
+                        console_clear_xy(s, x, s->y);
+                    }
                 break;
             }
+                break;
+            case 'm':
             console_handle_escape(s);
             break;
+            case 'n':
+                /* report cursor position */
+                /* TODO: send ESC[row;colR */
+                break;
+            case 's':
+                /* save cursor position */
+                s->x_saved = s->x;
+                s->y_saved = s->y;
+                break;
+            case 'u':
+                /* restore cursor position */
+                s->x = s->x_saved;
+                s->y = s->y_saved;
+                break;
+            default:
+#ifdef DEBUG_CONSOLE
+                fprintf(stderr, "unhandled escape character '%c'\n", ch);
+#endif
+                break;
+            }
+            break;
         }
     }
 }
@@ -884,16 +1018,6 @@ static int console_puts(CharDriverState *chr, const uint8_t *buf, int len)
     return len;
 }
 
-static void console_chr_add_read_handler(CharDriverState *chr, 
-                                         IOCanRWHandler *fd_can_read, 
-                                         IOReadHandler *fd_read, void *opaque)
-{
-    TextConsole *s = chr->opaque;
-    s->fd_can_read = fd_can_read;
-    s->fd_read = fd_read;
-    s->fd_opaque = opaque;
-}
-
 static void console_send_event(CharDriverState *chr, int event)
 {
     TextConsole *s = chr->opaque;
@@ -915,14 +1039,14 @@ static void kbd_send_chars(void *opaque)
     int len;
     uint8_t buf[16];
     
-    len = s->fd_can_read(s->fd_opaque);
+    len = qemu_chr_can_read(s->chr);
     if (len > s->out_fifo.count)
         len = s->out_fifo.count;
     if (len > 0) {
         if (len > sizeof(buf))
             len = sizeof(buf);
         qemu_fifo_read(&s->out_fifo, buf, len);
-        s->fd_read(s->fd_opaque, buf, len);
+        qemu_chr_read(s->chr, buf, len);
     }
     /* characters are pending: we send them a bit later (XXX:
        horrible, should change char device API) */
@@ -973,7 +1097,7 @@ void kbd_put_keysym(int keysym)
         } else {
                 *q++ = keysym;
         }
-        if (s->fd_read) {
+        if (s->chr->chr_read) {
             qemu_fifo_write(&s->out_fifo, buf, q - buf);
             kbd_send_chars(s);
         }
@@ -1059,9 +1183,9 @@ CharDriverState *text_console_init(DisplayState *ds)
     }
     chr->opaque = s;
     chr->chr_write = console_puts;
-    chr->chr_add_read_handler = console_chr_add_read_handler;
     chr->chr_send_event = console_send_event;
 
+    s->chr = chr;
     s->out_fifo.buf = s->out_fifo_buf;
     s->out_fifo.buf_size = sizeof(s->out_fifo_buf);
     s->kbd_timer = qemu_new_timer(rt_clock, kbd_send_chars, s);
@@ -1091,5 +1215,7 @@ CharDriverState *text_console_init(DisplayState *ds)
     s->t_attrib = s->t_attrib_default;
     text_console_resize(s);
 
+    qemu_chr_reset(chr);
+
     return chr;
 }
index a3c04f7083458837cbc402e72cad3b37eef85cae..1c4d4406a0c2b9a2d3d0cf63bbd963f0024ac244 100644 (file)
@@ -727,6 +727,13 @@ void page_unprotect_range(target_ulong data, target_ulong data_size);
 #define cpu_gen_code cpu_ppc_gen_code
 #define cpu_signal_handler cpu_ppc_signal_handler
 
+#elif defined(TARGET_M68K)
+#define CPUState CPUM68KState
+#define cpu_init cpu_m68k_init
+#define cpu_exec cpu_m68k_exec
+#define cpu_gen_code cpu_m68k_gen_code
+#define cpu_signal_handler cpu_m68k_signal_handler
+
 #elif defined(TARGET_MIPS)
 #define CPUState CPUMIPSState
 #define cpu_init cpu_mips_init
@@ -770,6 +777,7 @@ extern int code_copy_enabled;
 #define CPU_INTERRUPT_TIMER  0x08 /* internal timer exception pending */
 #define CPU_INTERRUPT_FIQ    0x10 /* Fast interrupt pending.  */
 #define CPU_INTERRUPT_HALT   0x20 /* CPU halt wanted */
+#define CPU_INTERRUPT_SMI    0x40 /* (x86 only) SMI interrupt pending */
 
 void cpu_interrupt(CPUState *s, int mask);
 void cpu_reset_interrupt(CPUState *env, int mask);
@@ -889,6 +897,7 @@ typedef uint32_t CPUReadMemoryFunc(void *opaque, target_phys_addr_t addr);
 void cpu_register_physical_memory(target_phys_addr_t start_addr, 
                                   unsigned long size,
                                   unsigned long phys_offset);
+uint32_t cpu_get_physical_page_desc(target_phys_addr_t addr);
 int cpu_register_io_memory(int io_index,
                            CPUReadMemoryFunc **mem_read,
                            CPUWriteMemoryFunc **mem_write,
@@ -1042,6 +1051,15 @@ static inline int64_t cpu_get_real_ticks (void)
         return rval.i64;
 #endif
 }
+#else
+/* The host CPU doesn't have an easily accessible cycle counter.
+   Just return a monotonically increasing vlue.  This will be totally wrong,
+   but hopefully better than nothing.  */
+static inline int64_t cpu_get_real_ticks (void)
+{
+    static int64_t ticks = 0;
+    return ticks++;
+}
 #endif
 
 /* profiling */
index 674c0bd3fb4a5ac37a7576387b9daffcc4679f1e..0b49c89913ef93f90a8f25c7385483af85f5bd6d 100644 (file)
@@ -80,6 +80,14 @@ typedef unsigned long ram_addr_t;
 #define TB_JMP_CACHE_BITS 12
 #define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS)
 
+/* Only the bottom TB_JMP_PAGE_BITS of the jump cache hash bits vary for
+   addresses on the same page.  The top bits are the same.  This allows
+   TLB invalidation to quickly clear a subset of the hash table.  */
+#define TB_JMP_PAGE_BITS (TB_JMP_CACHE_BITS / 2)
+#define TB_JMP_PAGE_SIZE (1 << TB_JMP_PAGE_BITS)
+#define TB_JMP_ADDR_MASK (TB_JMP_PAGE_SIZE - 1)
+#define TB_JMP_PAGE_MASK (TB_JMP_CACHE_SIZE - TB_JMP_PAGE_SIZE)
+
 #define CPU_TLB_BITS 8
 #define CPU_TLB_SIZE (1 << CPU_TLB_BITS)
 
index 60239d4b96e80e3b2438eced3af907b75750175d..058688fc77650ce68f3b2c5e39a66c1515f4ab95 100644 (file)
@@ -40,14 +40,14 @@ int tb_invalidated_flag;
 //#define DEBUG_EXEC
 //#define DEBUG_SIGNAL
 
-#if defined(TARGET_ARM) || defined(TARGET_SPARC)
+#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_M68K)
 /* XXX: unify with i386 target */
 void cpu_loop_exit(void)
 {
     longjmp(env->jmp_env, 1);
 }
 #endif
-#if !(defined(TARGET_SPARC) || defined(TARGET_SH4))
+#if !(defined(TARGET_SPARC) || defined(TARGET_SH4) || defined(TARGET_M68K))
 #define reg_T2
 #endif
 
@@ -194,6 +194,10 @@ static inline TranslationBlock *tb_find_fast(void)
     flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK);
     cs_base = 0;
     pc = env->PC;
+#elif defined(TARGET_M68K)
+    flags = env->fpcr & M68K_FPCR_PREC;
+    cs_base = 0;
+    pc = env->pc;
 #elif defined(TARGET_SH4)
     flags = env->sr & (SR_MD | SR_RB);
     cs_base = 0;         /* XXXXX */
@@ -222,43 +226,16 @@ static inline TranslationBlock *tb_find_fast(void)
 
 int cpu_exec(CPUState *env1)
 {
-    int saved_T0, saved_T1;
-#if defined(reg_T2)
-    int saved_T2;
-#endif
-    CPUState *saved_env;
-#if defined(TARGET_I386)
-#ifdef reg_EAX
-    int saved_EAX;
-#endif
-#ifdef reg_ECX
-    int saved_ECX;
-#endif
-#ifdef reg_EDX
-    int saved_EDX;
-#endif
-#ifdef reg_EBX
-    int saved_EBX;
-#endif
-#ifdef reg_ESP
-    int saved_ESP;
-#endif
-#ifdef reg_EBP
-    int saved_EBP;
-#endif
-#ifdef reg_ESI
-    int saved_ESI;
-#endif
-#ifdef reg_EDI
-    int saved_EDI;
-#endif
-#elif defined(TARGET_SPARC)
+#define DECLARE_HOST_REGS 1
+#include "hostregs_helper.h"
+#if defined(TARGET_SPARC)
 #if defined(reg_REGWPTR)
     uint32_t *saved_regwptr;
 #endif
 #endif
 #if defined(__sparc__) && !defined(HOST_SOLARIS)
-    int saved_i7, tmp_T0;
+    int saved_i7;
+    target_ulong tmp_T0;
 #endif
     int ret, interrupt_request;
     void (*gen_func)(void);
@@ -320,44 +297,15 @@ int cpu_exec(CPUState *env1)
     cpu_single_env = env1; 
 
     /* first we save global registers */
-    saved_env = env;
+#define SAVE_HOST_REGS 1
+#include "hostregs_helper.h"
     env = env1;
-    saved_T0 = T0;
-    saved_T1 = T1;
-#if defined(reg_T2)
-    saved_T2 = T2;
-#endif
 #if defined(__sparc__) && !defined(HOST_SOLARIS)
     /* we also save i7 because longjmp may not restore it */
     asm volatile ("mov %%i7, %0" : "=r" (saved_i7));
 #endif
 
 #if defined(TARGET_I386)
-#ifdef reg_EAX
-    saved_EAX = EAX;
-#endif
-#ifdef reg_ECX
-    saved_ECX = ECX;
-#endif
-#ifdef reg_EDX
-    saved_EDX = EDX;
-#endif
-#ifdef reg_EBX
-    saved_EBX = EBX;
-#endif
-#ifdef reg_ESP
-    saved_ESP = ESP;
-#endif
-#ifdef reg_EBP
-    saved_EBP = EBP;
-#endif
-#ifdef reg_ESI
-    saved_ESI = ESI;
-#endif
-#ifdef reg_EDI
-    saved_EDI = EDI;
-#endif
-
     env_to_regs();
     /* put eflags in CPU temporary format */
     CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
@@ -370,6 +318,10 @@ int cpu_exec(CPUState *env1)
     saved_regwptr = REGWPTR;
 #endif
 #elif defined(TARGET_PPC)
+#elif defined(TARGET_M68K)
+    env->cc_op = CC_OP_FLAGS;
+    env->cc_dest = env->sr & 0xf;
+    env->cc_x = (env->sr >> 4) & 1;
 #elif defined(TARGET_MIPS)
 #elif defined(TARGET_SH4)
     /* XXXXX */
@@ -390,7 +342,7 @@ int cpu_exec(CPUState *env1)
                     break;
                 } else if (env->user_mode_only) {
                     /* if user mode only, we simulate a fake exception
-                       which will be hanlded outside the cpu execution
+                       which will be handled outside the cpu execution
                        loop */
 #if defined(TARGET_I386)
                     do_interrupt_user(env->exception_index, 
@@ -458,8 +410,16 @@ int cpu_exec(CPUState *env1)
                 interrupt_request = env->interrupt_request;
                 if (__builtin_expect(interrupt_request, 0)) {
 #if defined(TARGET_I386)
-                    /* if hardware interrupt pending, we execute it */
-                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
+                    if ((interrupt_request & CPU_INTERRUPT_SMI) &&
+                        !(env->hflags & HF_SMM_MASK)) {
+                        env->interrupt_request &= ~CPU_INTERRUPT_SMI;
+                        do_smm_enter();
+#if defined(__sparc__) && !defined(HOST_SOLARIS)
+                        tmp_T0 = 0;
+#else
+                        T0 = 0;
+#endif
+                    } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
                         (env->eflags & IF_MASK) && 
                         !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
                         int intno;
@@ -519,7 +479,6 @@ int cpu_exec(CPUState *env1)
                         env->exception_index = EXCP_EXT_INTERRUPT;
                         env->error_code = 0;
                         do_interrupt(env);
-                        env->interrupt_request &= ~CPU_INTERRUPT_HARD;
 #if defined(__sparc__) && !defined(HOST_SOLARIS)
                         tmp_T0 = 0;
 #else
@@ -548,8 +507,10 @@ int cpu_exec(CPUState *env1)
                        //do_interrupt(0, 0, 0, 0, 0);
                        env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
                    } else if (interrupt_request & CPU_INTERRUPT_HALT) {
-                        env1->halted = 1;
-                        return EXCP_HALTED;
+                       env->interrupt_request &= ~CPU_INTERRUPT_HALT;
+                       env->halted = 1;
+                       env->exception_index = EXCP_HLT;
+                       cpu_loop_exit();
                     }
 #elif defined(TARGET_ARM)
                     if (interrupt_request & CPU_INTERRUPT_FIQ
@@ -622,6 +583,12 @@ int cpu_exec(CPUState *env1)
                     cpu_dump_state(env, logfile, fprintf, 0);
 #elif defined(TARGET_PPC)
                     cpu_dump_state(env, logfile, fprintf, 0);
+#elif defined(TARGET_M68K)
+                    cpu_m68k_flush_flags(env, env->cc_op);
+                    env->cc_op = CC_OP_FLAGS;
+                    env->sr = (env->sr & 0xffe0)
+                              | env->cc_dest | (env->cc_x << 4);
+                    cpu_dump_state(env, logfile, fprintf, 0);
 #elif defined(TARGET_MIPS)
                     cpu_dump_state(env, logfile, fprintf, 0);
 #elif defined(TARGET_SH4)
@@ -803,32 +770,6 @@ int cpu_exec(CPUState *env1)
 #endif
     /* restore flags in standard format */
     env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
-
-    /* restore global registers */
-#ifdef reg_EAX
-    EAX = saved_EAX;
-#endif
-#ifdef reg_ECX
-    ECX = saved_ECX;
-#endif
-#ifdef reg_EDX
-    EDX = saved_EDX;
-#endif
-#ifdef reg_EBX
-    EBX = saved_EBX;
-#endif
-#ifdef reg_ESP
-    ESP = saved_ESP;
-#endif
-#ifdef reg_EBP
-    EBP = saved_EBP;
-#endif
-#ifdef reg_ESI
-    ESI = saved_ESI;
-#endif
-#ifdef reg_EDI
-    EDI = saved_EDI;
-#endif
 #elif defined(TARGET_ARM)
     /* XXX: Save/restore host fpu exception state?.  */
 #elif defined(TARGET_SPARC)
@@ -836,21 +777,24 @@ int cpu_exec(CPUState *env1)
     REGWPTR = saved_regwptr;
 #endif
 #elif defined(TARGET_PPC)
+#elif defined(TARGET_M68K)
+    cpu_m68k_flush_flags(env, env->cc_op);
+    env->cc_op = CC_OP_FLAGS;
+    env->sr = (env->sr & 0xffe0)
+              | env->cc_dest | (env->cc_x << 4);
 #elif defined(TARGET_MIPS)
 #elif defined(TARGET_SH4)
     /* XXXXX */
 #else
 #error unsupported target CPU
 #endif
+
+    /* restore global registers */
 #if defined(__sparc__) && !defined(HOST_SOLARIS)
     asm volatile ("mov %0, %%i7" : : "r" (saved_i7));
 #endif
-    T0 = saved_T0;
-    T1 = saved_T1;
-#if defined(reg_T2)
-    T2 = saved_T2;
-#endif
-    env = saved_env;
+#include "hostregs_helper.h"
+
     /* fail safe : never use cpu_single_env outside cpu_exec() */
     cpu_single_env = NULL; 
     return ret;
@@ -1093,6 +1037,45 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
     return 1;
 }
 
+#elif defined(TARGET_M68K)
+static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
+                                    int is_write, sigset_t *old_set,
+                                    void *puc)
+{
+    TranslationBlock *tb;
+    int ret;
+
+    if (cpu_single_env)
+        env = cpu_single_env; /* XXX: find a correct solution for multithread */
+#if defined(DEBUG_SIGNAL)
+    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", 
+           pc, address, is_write, *(unsigned long *)old_set);
+#endif
+    /* XXX: locking issue */
+    if (is_write && page_unprotect(address, pc, puc)) {
+        return 1;
+    }
+    /* see if it is an MMU fault */
+    ret = cpu_m68k_handle_mmu_fault(env, address, is_write, 1, 0);
+    if (ret < 0)
+        return 0; /* not an MMU fault */
+    if (ret == 0)
+        return 1; /* the MMU fault was handled without causing real CPU fault */
+    /* now we have a real cpu fault */
+    tb = tb_find_pc(pc);
+    if (tb) {
+        /* the PC is inside the translated code. It means that we have
+           a virtual CPU fault */
+        cpu_restore_state(tb, env, pc, puc);
+    }
+    /* we restore the process signal mask as the sigreturn should
+       do it (XXX: use sigsetjmp) */
+    sigprocmask(SIG_SETMASK, old_set, NULL);
+    cpu_loop_exit();
+    /* never comes here */
+    return 1;
+}
+
 #elif defined (TARGET_MIPS)
 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
                                     int is_write, sigset_t *old_set,
@@ -1193,6 +1176,18 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
 
 #if defined(__i386__)
 
+#if defined(__APPLE__)
+# include <sys/ucontext.h>
+
+# define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
+# define TRAP_sig(context)    ((context)->uc_mcontext->es.trapno)
+# define ERROR_sig(context)   ((context)->uc_mcontext->es.err)
+#else
+# define EIP_sig(context)     ((context)->uc_mcontext.gregs[REG_EIP])
+# define TRAP_sig(context)    ((context)->uc_mcontext.gregs[REG_TRAPNO])
+# define ERROR_sig(context)   ((context)->uc_mcontext.gregs[REG_ERR])
+#endif
+
 #if defined(USE_CODE_COPY)
 static void cpu_send_trap(unsigned long pc, int trap, 
                           struct ucontext *uc)
@@ -1213,9 +1208,10 @@ static void cpu_send_trap(unsigned long pc, int trap,
 }
 #endif
 
-int cpu_signal_handler(int host_signum, struct siginfo *info, 
+int cpu_signal_handler(int host_signum, void *pinfo, 
                        void *puc)
 {
+    siginfo_t *info = pinfo;
     struct ucontext *uc = puc;
     unsigned long pc;
     int trapno;
@@ -1226,8 +1222,8 @@ int cpu_signal_handler(int host_signum, struct siginfo *info,
 #define REG_ERR    ERR
 #define REG_TRAPNO TRAPNO
 #endif
-    pc = uc->uc_mcontext.gregs[REG_EIP];
-    trapno = uc->uc_mcontext.gregs[REG_TRAPNO];
+    pc = EIP_sig(uc);
+    trapno = TRAP_sig(uc);
 #if defined(TARGET_I386) && defined(USE_CODE_COPY)
     if (trapno == 0x00 || trapno == 0x05) {
         /* send division by zero or bound exception */
@@ -1237,15 +1233,16 @@ int cpu_signal_handler(int host_signum, struct siginfo *info,
 #endif
         return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
                                  trapno == 0xe ? 
-                                 (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
+                                 (ERROR_sig(uc) >> 1) & 1 : 0,
                                  &uc->uc_sigmask, puc);
 }
 
 #elif defined(__x86_64__)
 
-int cpu_signal_handler(int host_signum, struct siginfo *info,
+int cpu_signal_handler(int host_signum, void *pinfo,
                        void *puc)
 {
+    siginfo_t *info = pinfo;
     struct ucontext *uc = puc;
     unsigned long pc;
 
@@ -1307,9 +1304,10 @@ typedef struct ucontext SIGCONTEXT;
 # define TRAP_sig(context)                     EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
 #endif /* __APPLE__ */
 
-int cpu_signal_handler(int host_signum, struct siginfo *info, 
+int cpu_signal_handler(int host_signum, void *pinfo, 
                        void *puc)
 {
+    siginfo_t *info = pinfo;
     struct ucontext *uc = puc;
     unsigned long pc;
     int is_write;
@@ -1330,9 +1328,10 @@ int cpu_signal_handler(int host_signum, struct siginfo *info,
 
 #elif defined(__alpha__)
 
-int cpu_signal_handler(int host_signum, struct siginfo *info, 
+int cpu_signal_handler(int host_signum, void *pinfo, 
                            void *puc)
 {
+    siginfo_t *info = pinfo;
     struct ucontext *uc = puc;
     uint32_t *pc = uc->uc_mcontext.sc_pc;
     uint32_t insn = *pc;
@@ -1359,9 +1358,10 @@ int cpu_signal_handler(int host_signum, struct siginfo *info,
 }
 #elif defined(__sparc__)
 
-int cpu_signal_handler(int host_signum, struct siginfo *info, 
+int cpu_signal_handler(int host_signum, void *pinfo, 
                        void *puc)
 {
+    siginfo_t *info = pinfo;
     uint32_t *regs = (uint32_t *)(info + 1);
     void *sigmask = (regs + 20);
     unsigned long pc;
@@ -1392,9 +1392,10 @@ int cpu_signal_handler(int host_signum, struct siginfo *info,
 
 #elif defined(__arm__)
 
-int cpu_signal_handler(int host_signum, struct siginfo *info, 
+int cpu_signal_handler(int host_signum, void *pinfo, 
                        void *puc)
 {
+    siginfo_t *info = pinfo;
     struct ucontext *uc = puc;
     unsigned long pc;
     int is_write;
@@ -1404,14 +1405,15 @@ int cpu_signal_handler(int host_signum, struct siginfo *info,
     is_write = 0;
     return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
                              is_write,
-                             &uc->uc_sigmask);
+                             &uc->uc_sigmask, puc);
 }
 
 #elif defined(__mc68000)
 
-int cpu_signal_handler(int host_signum, struct siginfo *info, 
+int cpu_signal_handler(int host_signum, void *pinfo, 
                        void *puc)
 {
+    siginfo_t *info = pinfo;
     struct ucontext *uc = puc;
     unsigned long pc;
     int is_write;
@@ -1431,8 +1433,9 @@ int cpu_signal_handler(int host_signum, struct siginfo *info,
 # define __ISR_VALID   1
 #endif
 
-int cpu_signal_handler(int host_signum, struct siginfo *info, void *puc)
+int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
 {
+    siginfo_t *info = pinfo;
     struct ucontext *uc = puc;
     unsigned long ip;
     int is_write = 0;
@@ -1459,9 +1462,10 @@ int cpu_signal_handler(int host_signum, struct siginfo *info, void *puc)
 
 #elif defined(__s390__)
 
-int cpu_signal_handler(int host_signum, struct siginfo *info, 
+int cpu_signal_handler(int host_signum, void *pinfo, 
                        void *puc)
 {
+    siginfo_t *info = pinfo;
     struct ucontext *uc = puc;
     unsigned long pc;
     int is_write;
diff --git a/tools/ioemu/cutils.c b/tools/ioemu/cutils.c
new file mode 100644 (file)
index 0000000..352c47e
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Simple C functions to supplement the C library
+ * 
+ * Copyright (c) 2006 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+
+void pstrcpy(char *buf, int buf_size, const char *str)
+{
+    int c;
+    char *q = buf;
+
+    if (buf_size <= 0)
+        return;
+
+    for(;;) {
+        c = *str++;
+        if (c == 0 || q >= buf + buf_size - 1)
+            break;
+        *q++ = c;
+    }
+    *q = '\0';
+}
+
+/* strcat and truncate. */
+char *pstrcat(char *buf, int buf_size, const char *s)
+{
+    int len;
+    len = strlen(buf);
+    if (len < buf_size) 
+        pstrcpy(buf + len, buf_size - len, s);
+    return buf;
+}
+
+int strstart(const char *str, const char *val, const char **ptr)
+{
+    const char *p, *q;
+    p = str;
+    q = val;
+    while (*q != '\0') {
+        if (*p != *q)
+            return 0;
+        p++;
+        q++;
+    }
+    if (ptr)
+        *ptr = p;
+    return 1;
+}
+
+int stristart(const char *str, const char *val, const char **ptr)
+{
+    const char *p, *q;
+    p = str;
+    q = val;
+    while (*q != '\0') {
+        if (toupper(*p) != toupper(*q))
+            return 0;
+        p++;
+        q++;
+    }
+    if (ptr)
+        *ptr = p;
+    return 1;
+}
index fd91b9220abff38d4cd4ea2bc0adad1d6603200c..2979927984e1553a64a2303f5dc19f9b605330a4 100644 (file)
@@ -186,14 +186,14 @@ void target_disas(FILE *out, target_ulong code, target_ulong size, int flags)
     disasm_info.mach = bfd_mach_ppc;
 #endif
     print_insn = print_insn_ppc;
+#elif defined(TARGET_M68K)
+    print_insn = print_insn_m68k;
 #elif defined(TARGET_MIPS)
 #ifdef TARGET_WORDS_BIGENDIAN
     print_insn = print_insn_big_mips;
 #else
     print_insn = print_insn_little_mips;
 #endif
-#elif defined(TARGET_M68K)
-    print_insn = print_insn_m68k;
 #elif defined(TARGET_SH4)
     disasm_info.mach = bfd_mach_sh4;
     print_insn = print_insn_sh;
@@ -271,11 +271,9 @@ void disas(FILE *out, void *code, unsigned long size)
     for (pc = (unsigned long)code; pc < (unsigned long)code + size; pc += count) {
        fprintf(out, "0x%08lx:  ", pc);
 #ifdef __arm__
-        /* since data are included in the code, it is better to
+        /* since data is included in the code, it is better to
            display code data too */
-        if (is_host) {
-            fprintf(out, "%08x  ", (int)bfd_getl32((const bfd_byte *)pc));
-        }
+        fprintf(out, "%08x  ", (int)bfd_getl32((const bfd_byte *)pc));
 #endif
        count = print_insn(pc, &disasm_info);
        fprintf(out, "\n");
@@ -387,14 +385,14 @@ void monitor_disas(CPUState *env,
     disasm_info.mach = bfd_mach_ppc;
 #endif
     print_insn = print_insn_ppc;
+#elif defined(TARGET_M68K)
+    print_insn = print_insn_m68k;
 #elif defined(TARGET_MIPS)
 #ifdef TARGET_WORDS_BIGENDIAN
     print_insn = print_insn_big_mips;
 #else
     print_insn = print_insn_little_mips;
 #endif
-#elif defined(TARGET_M68K)
-    print_insn = print_insn_m68k;
 #else
     term_printf("0x" TARGET_FMT_lx
                ": Asm output not supported on this arch\n", pc);
index 0c392283d41d4b09873f903727ae2312ce0d0947..7b313d62c72acdf3dc01202ae8f3db06e8b3e214 100644 (file)
@@ -62,6 +62,9 @@ typedef signed long long int64_t;
 #endif
 #endif
 
+/* XXX: This may be wrong for 64-bit ILP32 hosts.  */
+typedef void * host_reg_t;
+
 #define INT8_MIN               (-128)
 #define INT16_MIN              (-32767-1)
 #define INT32_MIN              (-2147483647-1)
@@ -188,7 +191,7 @@ extern int printf(const char *, ...);
 #endif
 
 /* force GCC to generate only one epilog at the end of the function */
-#define FORCE_RET() asm volatile ("");
+#define FORCE_RET() __asm__ __volatile__("" : : : "memory");
 
 #ifndef OPPROTO
 #define OPPROTO
index 5fb921e28ddd17e853e61935de568ca2f7cb3e82..bcfb86ea0dded612d51562e23cef3fe90041980a 100644 (file)
 typedef int32_t host_long;
 typedef uint32_t host_ulong;
 #define swabls(x) swab32s(x)
+#define swablss(x) swab32ss(x)
 #else
 typedef int64_t host_long;
 typedef uint64_t host_ulong;
 #define swabls(x) swab64s(x)
+#define swablss(x) swab64ss(x)
 #endif
 
 #ifdef ELF_USES_RELOCA
@@ -284,11 +286,21 @@ void swab32s(uint32_t *p)
     *p = bswap32(*p);
 }
 
+void swab32ss(int32_t *p)
+{
+    *p = bswap32(*p);
+}
+
 void swab64s(uint64_t *p)
 {
     *p = bswap64(*p);
 }
 
+void swab64ss(int64_t *p)
+{
+    *p = bswap64(*p);
+}
+
 uint16_t get16(uint16_t *p)
 {
     uint16_t val;
@@ -397,7 +409,7 @@ void elf_swap_rel(ELF_RELOC *rel)
     swabls(&rel->r_offset);
     swabls(&rel->r_info);
 #ifdef ELF_USES_RELOCA
-    swabls(&rel->r_addend);
+    swablss(&rel->r_addend);
 #endif
 }
 
@@ -505,7 +517,7 @@ int load_object(const char *filename)
     }
 
     sec = &shdr[ehdr.e_shstrndx];
-    shstr = sdata[ehdr.e_shstrndx];
+    shstr = (char *)sdata[ehdr.e_shstrndx];
 
     /* swap relocations */
     for(i = 0; i < ehdr.e_shnum; i++) {
@@ -541,7 +553,7 @@ int load_object(const char *filename)
     strtab_sec = &shdr[symtab_sec->sh_link];
 
     symtab = (ElfW(Sym) *)sdata[symtab_sec - shdr];
-    strtab = sdata[symtab_sec->sh_link];
+    strtab = (char *)sdata[symtab_sec->sh_link];
     
     nb_syms = symtab_sec->sh_size / sizeof(ElfW(Sym));
     if (do_swap) {
@@ -1255,90 +1267,149 @@ int arm_emit_ldr_info(const char *name, unsigned long start_offset,
 {
     uint8_t *p;
     uint32_t insn;
-    int offset, min_offset, pc_offset, data_size;
+    int offset, min_offset, pc_offset, data_size, spare, max_pool;
     uint8_t data_allocated[1024];
     unsigned int data_index;
+    int type;
     
     memset(data_allocated, 0, sizeof(data_allocated));
     
     p = p_start;
     min_offset = p_end - p_start;
+    spare = 0x7fffffff;
     while (p < p_start + min_offset) {
         insn = get32((uint32_t *)p);
+        /* TODO: Armv5e ldrd.  */
+        /* TODO: VFP load.  */
         if ((insn & 0x0d5f0000) == 0x051f0000) {
             /* ldr reg, [pc, #im] */
             offset = insn & 0xfff;
             if (!(insn & 0x00800000))
-                        offset = -offset;
+                offset = -offset;
+            max_pool = 4096;
+            type = 0;
+        } else if ((insn & 0x0e5f0f00) == 0x0c1f0100) {
+            /* FPA ldf.  */
+            offset = (insn & 0xff) << 2;
+            if (!(insn & 0x00800000))
+                offset = -offset;
+            max_pool = 1024;
+            type = 1;
+        } else if ((insn & 0x0fff0000) == 0x028f0000) {
+            /* Some gcc load a doubleword immediate with
+               add regN, pc, #imm
+               ldmia regN, {regN, regM}
+               Hope and pray the compiler never generates somethin like
+               add reg, pc, #imm1; ldr reg, [reg, #-imm2]; */
+            int r;
+
+            r = (insn & 0xf00) >> 7;
+            offset = ((insn & 0xff) >> r) | ((insn & 0xff) << (32 - r));
+            max_pool = 1024;
+            type = 2;
+        } else {
+            max_pool = 0;
+            type = -1;
+        }
+        if (type >= 0) {
+            /* PC-relative load needs fixing up.  */
+            if (spare > max_pool - offset)
+                spare = max_pool - offset;
             if ((offset & 3) !=0)
-                error("%s:%04x: ldr pc offset must be 32 bit aligned", 
+                error("%s:%04x: pc offset must be 32 bit aligned", 
+                      name, start_offset + p - p_start);
+            if (offset < 0)
+                error("%s:%04x: Embedded literal value",
                       name, start_offset + p - p_start);
             pc_offset = p - p_start + offset + 8;
             if (pc_offset <= (p - p_start) || 
                 pc_offset >= (p_end - p_start))
-                error("%s:%04x: ldr pc offset must point inside the function code", 
+                error("%s:%04x: pc offset must point inside the function code", 
                       name, start_offset + p - p_start);
             if (pc_offset < min_offset)
                 min_offset = pc_offset;
             if (outfile) {
-                /* ldr position */
+                /* The intruction position */
                 fprintf(outfile, "    arm_ldr_ptr->ptr = gen_code_ptr + %d;\n", 
                         p - p_start);
-                /* ldr data index */
-                data_index = ((p_end - p_start) - pc_offset - 4) >> 2;
-                fprintf(outfile, "    arm_ldr_ptr->data_ptr = arm_data_ptr + %d;\n", 
+                /* The position of the constant pool data.  */
+                data_index = ((p_end - p_start) - pc_offset) >> 2;
+                fprintf(outfile, "    arm_ldr_ptr->data_ptr = arm_data_ptr - %d;\n", 
                         data_index);
+                fprintf(outfile, "    arm_ldr_ptr->type = %d;\n", type);
                 fprintf(outfile, "    arm_ldr_ptr++;\n");
-                if (data_index >= sizeof(data_allocated))
-                    error("%s: too many data", name);
-                if (!data_allocated[data_index]) {
-                    ELF_RELOC *rel;
-                    int i, addend, type;
-                    const char *sym_name, *p;
-                    char relname[1024];
-
-                    data_allocated[data_index] = 1;
-
-                    /* data value */
-                    addend = get32((uint32_t *)(p_start + pc_offset));
-                    relname[0] = '\0';
-                    for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
-                        if (rel->r_offset == (pc_offset + start_offset)) {
-                            sym_name = get_rel_sym_name(rel);
-                            /* the compiler leave some unnecessary references to the code */
-                            get_reloc_expr(relname, sizeof(relname), sym_name);
-                            type = ELF32_R_TYPE(rel->r_info);
-                            if (type != R_ARM_ABS32)
-                                error("%s: unsupported data relocation", name);
-                            break;
-                        }
-                    }
-                    fprintf(outfile, "    arm_data_ptr[%d] = 0x%x",
-                            data_index, addend);
-                    if (relname[0] != '\0')
-                        fprintf(outfile, " + %s", relname);
-                    fprintf(outfile, ";\n");
-                }
             }
         }
         p += 4;
     }
+
+    /* Copy and relocate the constant pool data.  */
     data_size = (p_end - p_start) - min_offset;
     if (data_size > 0 && outfile) {
-        fprintf(outfile, "    arm_data_ptr += %d;\n", data_size >> 2);
+        spare += min_offset;
+        fprintf(outfile, "    arm_data_ptr -= %d;\n", data_size >> 2);
+        fprintf(outfile, "    arm_pool_ptr -= %d;\n", data_size);
+        fprintf(outfile, "    if (arm_pool_ptr > gen_code_ptr + %d)\n"
+                         "        arm_pool_ptr = gen_code_ptr + %d;\n",
+                         spare, spare);
+
+        data_index = 0;
+        for (pc_offset = min_offset;
+             pc_offset < p_end - p_start;
+             pc_offset += 4) {
+
+            ELF_RELOC *rel;
+            int i, addend, type;
+            const char *sym_name;
+            char relname[1024];
+
+            /* data value */
+            addend = get32((uint32_t *)(p_start + pc_offset));
+            relname[0] = '\0';
+            for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
+                if (rel->r_offset == (pc_offset + start_offset)) {
+                    sym_name = get_rel_sym_name(rel);
+                    /* the compiler leave some unnecessary references to the code */
+                    get_reloc_expr(relname, sizeof(relname), sym_name);
+                    type = ELF32_R_TYPE(rel->r_info);
+                    if (type != R_ARM_ABS32)
+                        error("%s: unsupported data relocation", name);
+                    break;
+                }
+            }
+            fprintf(outfile, "    arm_data_ptr[%d] = 0x%x",
+                    data_index, addend);
+            if (relname[0] != '\0')
+                fprintf(outfile, " + %s", relname);
+            fprintf(outfile, ";\n");
+
+            data_index++;
+        }
     }
 
-    /* the last instruction must be a mov pc, lr */
     if (p == p_start)
         goto arm_ret_error;
     p -= 4;
     insn = get32((uint32_t *)p);
-    if ((insn & 0xffff0000) != 0xe91b0000) {
+    /* The last instruction must be an ldm instruction.  There are several
+       forms generated by gcc:
+        ldmib sp, {..., pc}  (implies a sp adjustment of +4)
+        ldmia sp, {..., pc}
+        ldmea fp, {..., pc} */
+    if ((insn & 0xffff8000) == 0xe99d8000) {
+        if (outfile) {
+            fprintf(outfile,
+                    "    *(uint32_t *)(gen_code_ptr + %d) = 0xe28dd004;\n",
+                    p - p_start);
+        }
+        p += 4;
+    } else if ((insn & 0xffff8000) != 0xe89d8000
+        && (insn & 0xffff8000) != 0xe91b8000) {
     arm_ret_error:
         if (!outfile)
             printf("%s: invalid epilog\n", name);
     }
-    return p - p_start;            
+    return p - p_start;
 }
 #endif
 
@@ -1537,6 +1608,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
     }
 #elif defined(HOST_ARM)
     {
+        uint32_t insn;
+
         if ((p_end - p_start) <= 16)
             error("%s: function too small", name);
         if (get32((uint32_t *)p_start) != 0xe1a0c00d ||
@@ -1545,6 +1618,12 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
             error("%s: invalid prolog", name);
         p_start += 12;
         start_offset += 12;
+        insn = get32((uint32_t *)p_start);
+        if ((insn & 0xffffff00) == 0xe24dd000) {
+            /* Stack adjustment.  Assume op uses the frame pointer.  */
+            p_start -= 4;
+            start_offset -= 4;
+        }
         copy_size = arm_emit_ldr_info(name, start_offset, NULL, p_start, p_end, 
                                       relocs, nb_relocs);
     }
@@ -2282,7 +2361,37 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
                 int type;
                 int addend;
                 int reloc_offset;
-
+                uint32_t insn;
+
+                insn = get32((uint32_t *)(p_start + 4));
+                /* If prologue ends in sub sp, sp, #const then assume
+                   op has a stack frame and needs the frame pointer.  */
+                if ((insn & 0xffffff00) == 0xe24dd000) {
+                    int i;
+                    uint32_t opcode;
+                    opcode = 0xe28db000; /* add fp, sp, #0.  */
+#if 0
+/* ??? Need to undo the extra stack adjustment at the end of the op.
+   For now just leave the stack misaligned and hope it doesn't break anything
+   too important.  */
+                    if ((insn & 4) != 0) {
+                        /* Preserve doubleword stack alignment.  */
+                        fprintf(outfile,
+                                "    *(uint32_t *)(gen_code_ptr + 4)= 0x%x;\n",
+                                insn + 4);
+                        opcode -= 4;
+                    }
+#endif
+                    insn = get32((uint32_t *)(p_start - 4));
+                    /* Calculate the size of the saved registers,
+                       excluding pc.  */
+                    for (i = 0; i < 15; i++) {
+                        if (insn & (1 << i))
+                            opcode += 4;
+                    }
+                    fprintf(outfile,
+                            "    *(uint32_t *)gen_code_ptr = 0x%x;\n", opcode);
+                }
                 arm_emit_ldr_info(name, start_offset, outfile, p_start, p_end,
                                   relocs, nb_relocs);
 
@@ -2303,6 +2412,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
                                 reloc_offset, name, addend);
                         break;
                     case R_ARM_PC24:
+                    case R_ARM_JUMP24:
+                    case R_ARM_CALL:
                         fprintf(outfile, "    arm_reloc_pc24((uint32_t *)(gen_code_ptr + %d), 0x%x, %s);\n", 
                                 reloc_offset, addend, name);
                         break;
@@ -2407,6 +2518,28 @@ int gen_file(FILE *outfile, int out_type)
         
     } else {
         /* generate big code generation switch */
+
+#ifdef HOST_ARM
+        /* We need to know the size of all the ops so we can figure out when
+           to emit constant pools.  This must be consistent with opc.h.  */
+fprintf(outfile,
+"static const uint32_t arm_opc_size[] = {\n"
+"  0,\n" /* end */
+"  0,\n" /* nop */
+"  0,\n" /* nop1 */
+"  0,\n" /* nop2 */
+"  0,\n"); /* nop3 */
+        for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
+            const char *name;
+            name = get_sym_name(sym);
+            if (strstart(name, OP_PREFIX, NULL)) {
+                fprintf(outfile, "  %d,\n", sym->st_size);
+            }
+       }
+fprintf(outfile,
+"};\n");
+#endif
+
 fprintf(outfile,
 "int dyngen_code(uint8_t *gen_code_buf,\n"
 "                uint16_t *label_offsets, uint16_t *jmp_offsets,\n"
@@ -2417,10 +2550,36 @@ fprintf(outfile,
 "    const uint32_t *opparam_ptr;\n");
 
 #ifdef HOST_ARM
+/* Arm is tricky because it uses constant pools for loading immediate values.
+   We assume (and require) each function is code followed by a constant pool.
+   All the ops are small so this should be ok.  For each op we figure
+   out how much "spare" range we have in the load instructions.  This allows
+   us to insert subsequent ops in between the op and the constant pool,
+   eliminating the neeed to jump around the pool.
+
+   We currently generate:
+   
+   [ For this example we assume merging would move op1_pool out of range.
+     In practice we should be able to combine many ops before the offset
+     limits are reached. ]
+   op1_code;
+   op2_code;
+   goto op3;
+   op2_pool;
+   op1_pool;
+op3:
+   op3_code;
+   ret;
+   op3_pool;
+
+   Ideally we'd put op1_pool before op2_pool, but that requires two passes.
+ */
 fprintf(outfile,
 "    uint8_t *last_gen_code_ptr = gen_code_buf;\n"
 "    LDREntry *arm_ldr_ptr = arm_ldr_table;\n"
-"    uint32_t *arm_data_ptr = arm_data_table;\n");
+"    uint32_t *arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
+/* Initialise the parmissible pool offset to an arbitary large value.  */
+"    uint8_t *arm_pool_ptr = gen_code_buf + 0x1000000;\n");
 #endif
 #ifdef HOST_IA64
     {
@@ -2489,9 +2648,23 @@ fprintf(outfile,
        /* Generate prologue, if needed. */ 
 
 fprintf(outfile,
-"    for(;;) {\n"
-"        switch(*opc_ptr++) {\n"
-);
+"    for(;;) {\n");
+
+#ifdef HOST_ARM
+/* Generate constant pool if needed */
+fprintf(outfile,
+"            if (gen_code_ptr + arm_opc_size[*opc_ptr] >= arm_pool_ptr) {\n"
+"                gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, "
+"arm_ldr_ptr, arm_data_ptr, arm_data_table + ARM_LDR_TABLE_SIZE, 1);\n"
+"                last_gen_code_ptr = gen_code_ptr;\n"
+"                arm_ldr_ptr = arm_ldr_table;\n"
+"                arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
+"                arm_pool_ptr = gen_code_ptr + 0x1000000;\n"
+"            }\n");
+#endif
+
+fprintf(outfile,
+"        switch(*opc_ptr++) {\n");
 
         for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
             const char *name;
@@ -2525,17 +2698,6 @@ fprintf(outfile,
 "            goto the_end;\n"
 "        }\n");
 
-#ifdef HOST_ARM
-/* generate constant table if needed */
-fprintf(outfile,
-"        if ((gen_code_ptr - last_gen_code_ptr) >= (MAX_FRAG_SIZE - MAX_OP_SIZE)) {\n"
-"            gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, arm_ldr_ptr, arm_data_table, arm_data_ptr, 1);\n"
-"            last_gen_code_ptr = gen_code_ptr;\n"
-"            arm_ldr_ptr = arm_ldr_table;\n"
-"            arm_data_ptr = arm_data_table;\n"
-"        }\n");         
-#endif
-
 
 fprintf(outfile,
 "    }\n"
@@ -2553,7 +2715,10 @@ fprintf(outfile,
 
 /* generate some code patching */ 
 #ifdef HOST_ARM
-fprintf(outfile, "gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, arm_ldr_ptr, arm_data_table, arm_data_ptr, 0);\n");
+fprintf(outfile,
+"if (arm_data_ptr != arm_data_table + ARM_LDR_TABLE_SIZE)\n"
+"    gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, "
+"arm_ldr_ptr, arm_data_ptr, arm_data_table + ARM_LDR_TABLE_SIZE, 0);\n");
 #endif
     /* flush instruction cache */
     fprintf(outfile, "flush_icache_range((unsigned long)gen_code_buf, (unsigned long)gen_code_ptr);\n");
index fe0a9364e731c4e8e7fb4c5e088921010a043c59..2a87c448fd3f22f89c6681f6bff1f0c956736380 100644 (file)
@@ -19,7 +19,7 @@
  */
 
 int __op_param1, __op_param2, __op_param3;
-#ifdef __sparc__
+#if defined(__sparc__) || defined(__arm__)
   void __op_gen_label1(){}
   void __op_gen_label2(){}
   void __op_gen_label3(){}
@@ -145,18 +145,16 @@ void fix_bsr(void *p, int offset) {
 
 #ifdef __arm__
 
-#define MAX_OP_SIZE    (128 * 4) /* in bytes */
-/* max size of the code that can be generated without calling arm_flush_ldr */
-#define MAX_FRAG_SIZE  (1024 * 4) 
-//#define MAX_FRAG_SIZE  (135 * 4) /* for testing */ 
+#define ARM_LDR_TABLE_SIZE 1024
 
 typedef struct LDREntry {
     uint8_t *ptr;
     uint32_t *data_ptr;
+    unsigned type:2;
 } LDREntry;
 
 static LDREntry arm_ldr_table[1024];
-static uint32_t arm_data_table[1024];
+static uint32_t arm_data_table[ARM_LDR_TABLE_SIZE];
 
 extern char exec_loop;
 
@@ -175,8 +173,9 @@ static uint8_t *arm_flush_ldr(uint8_t *gen_code_ptr,
     int offset, data_size, target;
     uint8_t *data_ptr;
     uint32_t insn;
+    uint32_t mask;
  
-    data_size = (uint8_t *)data_end - (uint8_t *)data_start;
+    data_size = (data_end - data_start) << 2;
 
     if (gen_jmp) {
         /* generate branch to skip the data */
@@ -198,17 +197,48 @@ static uint8_t *arm_flush_ldr(uint8_t *gen_code_ptr,
         offset = ((unsigned long)(le->data_ptr) - (unsigned long)data_start) + 
             (unsigned long)data_ptr - 
             (unsigned long)ptr - 8;
-        insn = *ptr & ~(0xfff | 0x00800000);
         if (offset < 0) {
-            offset = - offset;
-        } else {
-            insn |= 0x00800000;
-        }
-        if (offset > 0xfff) {
-            fprintf(stderr, "Error ldr offset\n");
+            fprintf(stderr, "Negative constant pool offset\n");
             abort();
         }
-        insn |= offset;
+        switch (le->type) {
+          case 0: /* ldr */
+            mask = ~0x00800fff;
+            if (offset >= 4096) {
+                fprintf(stderr, "Bad ldr offset\n");
+                abort();
+            }
+            break;
+          case 1: /* ldc */
+            mask = ~0x008000ff;
+            if (offset >= 1024 ) {
+                fprintf(stderr, "Bad ldc offset\n");
+                abort();
+            }
+            break;
+          case 2: /* add */
+            mask = ~0xfff;
+            if (offset >= 1024 ) {
+                fprintf(stderr, "Bad add offset\n");
+                abort();
+            }
+            break;
+          default:
+            fprintf(stderr, "Bad pc relative fixup\n");
+            abort();
+          }
+        insn = *ptr & mask;
+        switch (le->type) {
+          case 0: /* ldr */
+            insn |= offset | 0x00800000;
+            break;
+          case 1: /* ldc */
+            insn |= (offset >> 2) | 0x00800000;
+            break;
+          case 2: /* add */
+            insn |= (offset >> 2) | 0xf00;
+            break;
+          }
         *ptr = insn;
     }
     return gen_code_ptr;
index 8ceb949769fa18dab28378a037cb5ecbcba2678b..1825d50e82a20cef8bad0511ae3fb355c884832e 100644 (file)
@@ -502,6 +502,8 @@ typedef struct {
 #define R_ARM_GOTPC            25      /* 32 bit PC relative offset to GOT */
 #define R_ARM_GOT32            26      /* 32 bit GOT entry */
 #define R_ARM_PLT32            27      /* 32 bit PLT address */
+#define R_ARM_CALL              28
+#define R_ARM_JUMP24            29
 #define R_ARM_GNU_VTENTRY      100
 #define R_ARM_GNU_VTINHERIT    101
 #define R_ARM_THM_PC11         102     /* thumb unconditional branch */
index 122bf10c1f785663ce4a453f4209481bc8cf83ff..abcce093ef868fb93c4220ac922e510f58dedd52 100644 (file)
@@ -153,6 +153,9 @@ int glue(load_elf, SZ)(int fd, int64_t virt_to_phys_addend,
         glue(bswap_ehdr, SZ)(&ehdr);
     }
 
+    if (ELF_MACHINE != ehdr.e_machine)
+        goto fail;
+
     if (pentry)
        *pentry = (uint64_t)ehdr.e_entry;
 
@@ -202,4 +205,3 @@ int glue(load_elf, SZ)(int fd, int64_t virt_to_phys_addend,
     qemu_free(phdr);
     return -1;
 }
-
index eb4fa76b6cdf007d278d0ea327760d0078ecc3f8..91d8cf7c97e9fa42bdb4a27857035329c3bb2a8a 100644 (file)
@@ -196,9 +196,19 @@ typedef struct TranslationBlock {
     struct TranslationBlock *jmp_first;
 } TranslationBlock;
 
+static inline unsigned int tb_jmp_cache_hash_page(target_ulong pc)
+{
+    target_ulong tmp;
+    tmp = pc ^ (pc >> (TARGET_PAGE_BITS - TB_JMP_PAGE_BITS));
+    return (tmp >> TB_JMP_PAGE_BITS) & TB_JMP_PAGE_MASK;
+}
+
 static inline unsigned int tb_jmp_cache_hash_func(target_ulong pc)
 {
-    return (pc ^ (pc >> TB_JMP_CACHE_BITS)) & (TB_JMP_CACHE_SIZE - 1);
+    target_ulong tmp;
+    tmp = pc ^ (pc >> (TARGET_PAGE_BITS - TB_JMP_PAGE_BITS));
+    return (((tmp >> TB_JMP_PAGE_BITS) & TB_JMP_PAGE_MASK) |
+           (tmp & TB_JMP_ADDR_MASK));
 }
 
 static inline unsigned int tb_phys_hash_func(unsigned long pc)
index 88acff0917caa1d86a19b5e5f2c04d88656de91f..ae2d825da34f44036eec24378c2e114ab9964996 100644 (file)
@@ -41,6 +41,7 @@
 //#define DEBUG_TB_INVALIDATE
 //#define DEBUG_FLUSH
 //#define DEBUG_TLB
+//#define DEBUG_UNASSIGNED
 
 /* make various TB consistency checks */
 //#define DEBUG_TB_CHECK 
@@ -1288,14 +1289,13 @@ void tlb_flush_page(CPUState *env, target_ulong addr)
     tlb_flush_entry(&env->tlb_table[0][i], addr);
     tlb_flush_entry(&env->tlb_table[1][i], addr);
 
-    for(i = 0; i < TB_JMP_CACHE_SIZE; i++) {
-        tb = env->tb_jmp_cache[i];
-        if (tb && 
-            ((tb->pc & TARGET_PAGE_MASK) == addr ||
-             ((tb->pc + tb->size - 1) & TARGET_PAGE_MASK) == addr)) {
-            env->tb_jmp_cache[i] = NULL;
-        }
-    }
+    /* Discard jump cache entries for any tb which might potentially
+       overlap the flushed page.  */
+    i = tb_jmp_cache_hash_page(addr - TARGET_PAGE_SIZE);
+    memset (&env->tb_jmp_cache[i], 0, TB_JMP_PAGE_SIZE * sizeof(tb));
+
+    i = tb_jmp_cache_hash_page(addr);
+    memset (&env->tb_jmp_cache[i], 0, TB_JMP_PAGE_SIZE * sizeof(tb));
 
 #if !defined(CONFIG_SOFTMMU)
     if (addr < MMAP_AREA_END)
@@ -1801,13 +1801,30 @@ void cpu_register_physical_memory(target_phys_addr_t start_addr,
     }
 }
 
+/* XXX: temporary until new memory mapping API */
+uint32_t cpu_get_physical_page_desc(target_phys_addr_t addr)
+{
+    PhysPageDesc *p;
+
+    p = phys_page_find(addr >> TARGET_PAGE_BITS);
+    if (!p)
+        return IO_MEM_UNASSIGNED;
+    return p->phys_offset;
+}
+
 static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
 {
+#ifdef DEBUG_UNASSIGNED
+    printf("Unassigned mem read  0x%08x\n", (int)addr);
+#endif
     return 0;
 }
 
 static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
 {
+#ifdef DEBUG_UNASSIGNED
+    printf("Unassigned mem write 0x%08x = 0x%x\n", (int)addr, val);
+#endif
 }
 
 static CPUReadMemoryFunc *unassigned_mem_read[3] = {
index 0e2bf27a9d41f2819cce42d6c2c0cdea42108dc3..cd33c001d24ba65e9a5a00f609360c276b370661 100644 (file)
@@ -1,7 +1,7 @@
-/softfloat-macros.h/1.1/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/softfloat-native.c/1.4/Sun Aug  6 01:03:50 2006//Trelease_0_8_2
-/softfloat-native.h/1.6/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/softfloat-specialize.h/1.1/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/softfloat.c/1.2/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/softfloat.h/1.3/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
+/softfloat-macros.h/1.1/Wed Oct 18 10:11:20 2006//Trelease_0_9_0
+/softfloat-native.c/1.6/Thu May  3 17:18:00 2007//Trelease_0_9_0
+/softfloat-native.h/1.8/Thu May  3 17:18:00 2007//Trelease_0_9_0
+/softfloat-specialize.h/1.2/Thu May  3 17:18:00 2007//Trelease_0_9_0
+/softfloat.c/1.4/Thu May  3 17:18:00 2007//Trelease_0_9_0
+/softfloat.h/1.5/Thu May  3 17:18:00 2007//Trelease_0_9_0
 D
index bd48d406fa1b16a1721b34dc4bb6979acc4274da..eed9f4a4fb93e992c8c20b591822041f09711c7e 100644 (file)
@@ -1 +1 @@
-Nrelease_0_8_2
+Nrelease_0_9_0
index bbdb3d66d991431f227109a57661e71fad5ea67b..f20d5c45f67e18e74fcdbba21b957a0855415135 100644 (file)
@@ -149,7 +149,7 @@ float32 float32_sqrt( float32 a STATUS_PARAM)
 {
     return sqrtf(a);
 }
-char float32_compare( float32 a, float32 b STATUS_PARAM )
+int float32_compare( float32 a, float32 b STATUS_PARAM )
 {
     if (a < b) {
         return -1;
@@ -161,7 +161,7 @@ char float32_compare( float32 a, float32 b STATUS_PARAM )
         return 2;
     }
 }
-char float32_compare_quiet( float32 a, float32 b STATUS_PARAM )
+int float32_compare_quiet( float32 a, float32 b STATUS_PARAM )
 {
     if (isless(a, b)) {
         return -1;
@@ -173,7 +173,7 @@ char float32_compare_quiet( float32 a, float32 b STATUS_PARAM )
         return 2;
     }
 }
-char float32_is_signaling_nan( float32 a1)
+int float32_is_signaling_nan( float32 a1)
 {
     float32u u;
     uint32_t a;
@@ -221,6 +221,11 @@ float128 float64_to_float128( float64 a STATUS_PARAM)
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE double-precision operations.
 *----------------------------------------------------------------------------*/
+float64 float64_trunc_to_int( float64 a STATUS_PARAM )
+{
+    return trunc(a);
+}
+
 float64 float64_round_to_int( float64 a STATUS_PARAM )
 {
 #if defined(__arm__)
@@ -253,7 +258,7 @@ float64 float64_sqrt( float64 a STATUS_PARAM)
 {
     return sqrt(a);
 }
-char float64_compare( float64 a, float64 b STATUS_PARAM )
+int float64_compare( float64 a, float64 b STATUS_PARAM )
 {
     if (a < b) {
         return -1;
@@ -265,7 +270,7 @@ char float64_compare( float64 a, float64 b STATUS_PARAM )
         return 2;
     }
 }
-char float64_compare_quiet( float64 a, float64 b STATUS_PARAM )
+int float64_compare_quiet( float64 a, float64 b STATUS_PARAM )
 {
     if (isless(a, b)) {
         return -1;
@@ -277,7 +282,7 @@ char float64_compare_quiet( float64 a, float64 b STATUS_PARAM )
         return 2;
     }
 }
-char float64_is_signaling_nan( float64 a1)
+int float64_is_signaling_nan( float64 a1)
 {
     float64u u;
     uint64_t a;
@@ -289,6 +294,17 @@ char float64_is_signaling_nan( float64 a1)
 
 }
 
+int float64_is_nan( float64 a1 )
+{
+    float64u u;
+    uint64_t a;
+    u.f = a1;
+    a = u.i;
+
+    return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) );
+
+}
+
 #ifdef FLOATX80
 
 /*----------------------------------------------------------------------------
@@ -334,7 +350,7 @@ floatx80 floatx80_sqrt( floatx80 a STATUS_PARAM)
 {
     return sqrtl(a);
 }
-char floatx80_compare( floatx80 a, floatx80 b STATUS_PARAM )
+int floatx80_compare( floatx80 a, floatx80 b STATUS_PARAM )
 {
     if (a < b) {
         return -1;
@@ -346,7 +362,7 @@ char floatx80_compare( floatx80 a, floatx80 b STATUS_PARAM )
         return 2;
     }
 }
-char floatx80_compare_quiet( floatx80 a, floatx80 b STATUS_PARAM )
+int floatx80_compare_quiet( floatx80 a, floatx80 b STATUS_PARAM )
 {
     if (isless(a, b)) {
         return -1;
@@ -358,7 +374,7 @@ char floatx80_compare_quiet( floatx80 a, floatx80 b STATUS_PARAM )
         return 2;
     }
 }
-char floatx80_is_signaling_nan( floatx80 a1)
+int floatx80_is_signaling_nan( floatx80 a1)
 {
     floatx80u u;
     u.f = a1;
index e7c08b89f4e2698117c80022433a4e49cbf7bd8d..8c27708771e1bb7f29119a755324f5e0aace73e3 100644 (file)
@@ -152,38 +152,38 @@ INLINE float32 float32_div( float32 a, float32 b STATUS_PARAM)
 }
 float32 float32_rem( float32, float32  STATUS_PARAM);
 float32 float32_sqrt( float32  STATUS_PARAM);
-INLINE char float32_eq( float32 a, float32 b STATUS_PARAM)
+INLINE int float32_eq( float32 a, float32 b STATUS_PARAM)
 {
     return a == b;
 }
-INLINE char float32_le( float32 a, float32 b STATUS_PARAM)
+INLINE int float32_le( float32 a, float32 b STATUS_PARAM)
 {
     return a <= b;
 }
-INLINE char float32_lt( float32 a, float32 b STATUS_PARAM)
+INLINE int float32_lt( float32 a, float32 b STATUS_PARAM)
 {
     return a < b;
 }
-INLINE char float32_eq_signaling( float32 a, float32 b STATUS_PARAM)
+INLINE int float32_eq_signaling( float32 a, float32 b STATUS_PARAM)
 {
     return a <= b && a >= b;
 }
-INLINE char float32_le_quiet( float32 a, float32 b STATUS_PARAM)
+INLINE int float32_le_quiet( float32 a, float32 b STATUS_PARAM)
 {
     return islessequal(a, b);
 }
-INLINE char float32_lt_quiet( float32 a, float32 b STATUS_PARAM)
+INLINE int float32_lt_quiet( float32 a, float32 b STATUS_PARAM)
 {
     return isless(a, b);
 }
-INLINE char float32_unordered( float32 a, float32 b STATUS_PARAM)
+INLINE int float32_unordered( float32 a, float32 b STATUS_PARAM)
 {
     return isunordered(a, b);
 
 }
-char float32_compare( float32, float32 STATUS_PARAM );
-char float32_compare_quiet( float32, float32 STATUS_PARAM );
-char float32_is_signaling_nan( float32 );
+int float32_compare( float32, float32 STATUS_PARAM );
+int float32_compare_quiet( float32, float32 STATUS_PARAM );
+int float32_is_signaling_nan( float32 );
 
 INLINE float32 float32_abs(float32 a)
 {
@@ -214,6 +214,7 @@ float128 float64_to_float128( float64 STATUS_PARAM );
 | Software IEC/IEEE double-precision operations.
 *----------------------------------------------------------------------------*/
 float64 float64_round_to_int( float64 STATUS_PARAM );
+float64 float64_trunc_to_int( float64 STATUS_PARAM );
 INLINE float64 float64_add( float64 a, float64 b STATUS_PARAM)
 {
     return a + b;
@@ -232,39 +233,40 @@ INLINE float64 float64_div( float64 a, float64 b STATUS_PARAM)
 }
 float64 float64_rem( float64, float64 STATUS_PARAM );
 float64 float64_sqrt( float64 STATUS_PARAM );
-INLINE char float64_eq( float64 a, float64 b STATUS_PARAM)
+INLINE int float64_eq( float64 a, float64 b STATUS_PARAM)
 {
     return a == b;
 }
-INLINE char float64_le( float64 a, float64 b STATUS_PARAM)
+INLINE int float64_le( float64 a, float64 b STATUS_PARAM)
 {
     return a <= b;
 }
-INLINE char float64_lt( float64 a, float64 b STATUS_PARAM)
+INLINE int float64_lt( float64 a, float64 b STATUS_PARAM)
 {
     return a < b;
 }
-INLINE char float64_eq_signaling( float64 a, float64 b STATUS_PARAM)
+INLINE int float64_eq_signaling( float64 a, float64 b STATUS_PARAM)
 {
     return a <= b && a >= b;
 }
-INLINE char float64_le_quiet( float64 a, float64 b STATUS_PARAM)
+INLINE int float64_le_quiet( float64 a, float64 b STATUS_PARAM)
 {
     return islessequal(a, b);
 }
-INLINE char float64_lt_quiet( float64 a, float64 b STATUS_PARAM)
+INLINE int float64_lt_quiet( float64 a, float64 b STATUS_PARAM)
 {
     return isless(a, b);
 
 }
-INLINE char float64_unordered( float64 a, float64 b STATUS_PARAM)
+INLINE int float64_unordered( float64 a, float64 b STATUS_PARAM)
 {
     return isunordered(a, b);
 
 }
-char float64_compare( float64, float64 STATUS_PARAM );
-char float64_compare_quiet( float64, float64 STATUS_PARAM );
-char float64_is_signaling_nan( float64 );
+int float64_compare( float64, float64 STATUS_PARAM );
+int float64_compare_quiet( float64, float64 STATUS_PARAM );
+int float64_is_signaling_nan( float64 );
+int float64_is_nan( float64 );
 
 INLINE float64 float64_abs(float64 a)
 {
@@ -313,39 +315,39 @@ INLINE floatx80 floatx80_div( floatx80 a, floatx80 b STATUS_PARAM)
 }
 floatx80 floatx80_rem( floatx80, floatx80 STATUS_PARAM );
 floatx80 floatx80_sqrt( floatx80 STATUS_PARAM );
-INLINE char floatx80_eq( floatx80 a, floatx80 b STATUS_PARAM)
+INLINE int floatx80_eq( floatx80 a, floatx80 b STATUS_PARAM)
 {
     return a == b;
 }
-INLINE char floatx80_le( floatx80 a, floatx80 b STATUS_PARAM)
+INLINE int floatx80_le( floatx80 a, floatx80 b STATUS_PARAM)
 {
     return a <= b;
 }
-INLINE char floatx80_lt( floatx80 a, floatx80 b STATUS_PARAM)
+INLINE int floatx80_lt( floatx80 a, floatx80 b STATUS_PARAM)
 {
     return a < b;
 }
-INLINE char floatx80_eq_signaling( floatx80 a, floatx80 b STATUS_PARAM)
+INLINE int floatx80_eq_signaling( floatx80 a, floatx80 b STATUS_PARAM)
 {
     return a <= b && a >= b;
 }
-INLINE char floatx80_le_quiet( floatx80 a, floatx80 b STATUS_PARAM)
+INLINE int floatx80_le_quiet( floatx80 a, floatx80 b STATUS_PARAM)
 {
     return islessequal(a, b);
 }
-INLINE char floatx80_lt_quiet( floatx80 a, floatx80 b STATUS_PARAM)
+INLINE int floatx80_lt_quiet( floatx80 a, floatx80 b STATUS_PARAM)
 {
     return isless(a, b);
 
 }
-INLINE char floatx80_unordered( floatx80 a, floatx80 b STATUS_PARAM)
+INLINE int floatx80_unordered( floatx80 a, floatx80 b STATUS_PARAM)
 {
     return isunordered(a, b);
 
 }
-char floatx80_compare( floatx80, floatx80 STATUS_PARAM );
-char floatx80_compare_quiet( floatx80, floatx80 STATUS_PARAM );
-char floatx80_is_signaling_nan( floatx80 );
+int floatx80_compare( floatx80, floatx80 STATUS_PARAM );
+int floatx80_compare_quiet( floatx80, floatx80 STATUS_PARAM );
+int floatx80_is_signaling_nan( floatx80 );
 
 INLINE floatx80 floatx80_abs(floatx80 a)
 {
index d430f58a719cd074e92b984e65150036c955c29f..f9b6f0cbc64837093b007fd7ed2bb2e095e3b588 100644 (file)
@@ -68,7 +68,7 @@ typedef struct {
 | otherwise returns 0.
 *----------------------------------------------------------------------------*/
 
-flag float32_is_nan( float32 a )
+int float32_is_nan( float32 a )
 {
 
     return ( 0xFF000000 < (bits32) ( a<<1 ) );
@@ -80,7 +80,7 @@ flag float32_is_nan( float32 a )
 | NaN; otherwise returns 0.
 *----------------------------------------------------------------------------*/
 
-flag float32_is_signaling_nan( float32 a )
+int float32_is_signaling_nan( float32 a )
 {
 
     return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
@@ -161,7 +161,7 @@ static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM)
 | otherwise returns 0.
 *----------------------------------------------------------------------------*/
 
-flag float64_is_nan( float64 a )
+int float64_is_nan( float64 a )
 {
 
     return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) );
@@ -173,7 +173,7 @@ flag float64_is_nan( float64 a )
 | NaN; otherwise returns 0.
 *----------------------------------------------------------------------------*/
 
-flag float64_is_signaling_nan( float64 a )
+int float64_is_signaling_nan( float64 a )
 {
 
     return
@@ -264,7 +264,7 @@ static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM)
 | NaN; otherwise returns 0.
 *----------------------------------------------------------------------------*/
 
-flag floatx80_is_nan( floatx80 a )
+int floatx80_is_nan( floatx80 a )
 {
 
     return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
@@ -276,7 +276,7 @@ flag floatx80_is_nan( floatx80 a )
 | signaling NaN; otherwise returns 0.
 *----------------------------------------------------------------------------*/
 
-flag floatx80_is_signaling_nan( floatx80 a )
+int floatx80_is_signaling_nan( floatx80 a )
 {
     bits64 aLow;
 
@@ -371,7 +371,7 @@ static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM)
 | otherwise returns 0.
 *----------------------------------------------------------------------------*/
 
-flag float128_is_nan( float128 a )
+int float128_is_nan( float128 a )
 {
 
     return
@@ -385,7 +385,7 @@ flag float128_is_nan( float128 a )
 | signaling NaN; otherwise returns 0.
 *----------------------------------------------------------------------------*/
 
-flag float128_is_signaling_nan( float128 a )
+int float128_is_signaling_nan( float128 a )
 {
 
     return
index 5e846200ae7470a6df6b9c5d3872120eba73c924..5dbfa81e43bbdbf40c2e629ac62b5f91e4e67378 100644 (file)
@@ -2023,7 +2023,7 @@ float32 float32_sqrt( float32 a STATUS_PARAM )
 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
-flag float32_eq( float32 a, float32 b STATUS_PARAM )
+int float32_eq( float32 a, float32 b STATUS_PARAM )
 {
 
     if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
@@ -2045,7 +2045,7 @@ flag float32_eq( float32 a, float32 b STATUS_PARAM )
 | Arithmetic.
 *----------------------------------------------------------------------------*/
 
-flag float32_le( float32 a, float32 b STATUS_PARAM )
+int float32_le( float32 a, float32 b STATUS_PARAM )
 {
     flag aSign, bSign;
 
@@ -2068,7 +2068,7 @@ flag float32_le( float32 a, float32 b STATUS_PARAM )
 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
-flag float32_lt( float32 a, float32 b STATUS_PARAM )
+int float32_lt( float32 a, float32 b STATUS_PARAM )
 {
     flag aSign, bSign;
 
@@ -2092,7 +2092,7 @@ flag float32_lt( float32 a, float32 b STATUS_PARAM )
 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
-flag float32_eq_signaling( float32 a, float32 b STATUS_PARAM )
+int float32_eq_signaling( float32 a, float32 b STATUS_PARAM )
 {
 
     if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
@@ -2112,7 +2112,7 @@ flag float32_eq_signaling( float32 a, float32 b STATUS_PARAM )
 | IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
-flag float32_le_quiet( float32 a, float32 b STATUS_PARAM )
+int float32_le_quiet( float32 a, float32 b STATUS_PARAM )
 {
     flag aSign, bSign;
 
@@ -2138,7 +2138,7 @@ flag float32_le_quiet( float32 a, float32 b STATUS_PARAM )
 | Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
-flag float32_lt_quiet( float32 a, float32 b STATUS_PARAM )
+int float32_lt_quiet( float32 a, float32 b STATUS_PARAM )
 {
     flag aSign, bSign;
 
@@ -2483,6 +2483,17 @@ float64 float64_round_to_int( float64 a STATUS_PARAM )
 
 }
 
+float64 float64_trunc_to_int( float64 a STATUS_PARAM)
+{
+    int oldmode;
+    float64 res;
+    oldmode = STATUS(float_rounding_mode);
+    STATUS(float_rounding_mode) = float_round_to_zero;
+    res = float64_round_to_int(a STATUS_VAR);
+    STATUS(float_rounding_mode) = oldmode;
+    return res;
+}
+
 /*----------------------------------------------------------------------------
 | Returns the result of adding the absolute values of the double-precision
 | floating-point values `a' and `b'.  If `zSign' is 1, the sum is negated
@@ -2941,7 +2952,7 @@ float64 float64_sqrt( float64 a STATUS_PARAM )
 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
-flag float64_eq( float64 a, float64 b STATUS_PARAM )
+int float64_eq( float64 a, float64 b STATUS_PARAM )
 {
 
     if (    ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
@@ -2963,7 +2974,7 @@ flag float64_eq( float64 a, float64 b STATUS_PARAM )
 | Arithmetic.
 *----------------------------------------------------------------------------*/
 
-flag float64_le( float64 a, float64 b STATUS_PARAM )
+int float64_le( float64 a, float64 b STATUS_PARAM )
 {
     flag aSign, bSign;
 
@@ -2986,7 +2997,7 @@ flag float64_le( float64 a, float64 b STATUS_PARAM )
 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
-flag float64_lt( float64 a, float64 b STATUS_PARAM )
+int float64_lt( float64 a, float64 b STATUS_PARAM )
 {
     flag aSign, bSign;
 
@@ -3010,7 +3021,7 @@ flag float64_lt( float64 a, float64 b STATUS_PARAM )
 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
-flag float64_eq_signaling( float64 a, float64 b STATUS_PARAM )
+int float64_eq_signaling( float64 a, float64 b STATUS_PARAM )
 {
 
     if (    ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
@@ -3030,7 +3041,7 @@ flag float64_eq_signaling( float64 a, float64 b STATUS_PARAM )
 | IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
-flag float64_le_quiet( float64 a, float64 b STATUS_PARAM )
+int float64_le_quiet( float64 a, float64 b STATUS_PARAM )
 {
     flag aSign, bSign;
 
@@ -3056,7 +3067,7 @@ flag float64_le_quiet( float64 a, float64 b STATUS_PARAM )
 | Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
-flag float64_lt_quiet( float64 a, float64 b STATUS_PARAM )
+int float64_lt_quiet( float64 a, float64 b STATUS_PARAM )
 {
     flag aSign, bSign;
 
@@ -3879,7 +3890,7 @@ floatx80 floatx80_sqrt( floatx80 a STATUS_PARAM )
 | Arithmetic.
 *----------------------------------------------------------------------------*/
 
-flag floatx80_eq( floatx80 a, floatx80 b STATUS_PARAM )
+int floatx80_eq( floatx80 a, floatx80 b STATUS_PARAM )
 {
 
     if (    (    ( extractFloatx80Exp( a ) == 0x7FFF )
@@ -3909,7 +3920,7 @@ flag floatx80_eq( floatx80 a, floatx80 b STATUS_PARAM )
 | Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
-flag floatx80_le( floatx80 a, floatx80 b STATUS_PARAM )
+int floatx80_le( floatx80 a, floatx80 b STATUS_PARAM )
 {
     flag aSign, bSign;
 
@@ -3942,7 +3953,7 @@ flag floatx80_le( floatx80 a, floatx80 b STATUS_PARAM )
 | Arithmetic.
 *----------------------------------------------------------------------------*/
 
-flag floatx80_lt( floatx80 a, floatx80 b STATUS_PARAM )
+int floatx80_lt( floatx80 a, floatx80 b STATUS_PARAM )
 {
     flag aSign, bSign;
 
@@ -3975,7 +3986,7 @@ flag floatx80_lt( floatx80 a, floatx80 b STATUS_PARAM )
 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
-flag floatx80_eq_signaling( floatx80 a, floatx80 b STATUS_PARAM )
+int floatx80_eq_signaling( floatx80 a, floatx80 b STATUS_PARAM )
 {
 
     if (    (    ( extractFloatx80Exp( a ) == 0x7FFF )
@@ -4002,7 +4013,7 @@ flag floatx80_eq_signaling( floatx80 a, floatx80 b STATUS_PARAM )
 | to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
-flag floatx80_le_quiet( floatx80 a, floatx80 b STATUS_PARAM )
+int floatx80_le_quiet( floatx80 a, floatx80 b STATUS_PARAM )
 {
     flag aSign, bSign;
 
@@ -4038,7 +4049,7 @@ flag floatx80_le_quiet( floatx80 a, floatx80 b STATUS_PARAM )
 | IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
-flag floatx80_lt_quiet( floatx80 a, floatx80 b STATUS_PARAM )
+int floatx80_lt_quiet( floatx80 a, floatx80 b STATUS_PARAM )
 {
     flag aSign, bSign;
 
@@ -4999,7 +5010,7 @@ float128 float128_sqrt( float128 a STATUS_PARAM )
 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
-flag float128_eq( float128 a, float128 b STATUS_PARAM )
+int float128_eq( float128 a, float128 b STATUS_PARAM )
 {
 
     if (    (    ( extractFloat128Exp( a ) == 0x7FFF )
@@ -5029,7 +5040,7 @@ flag float128_eq( float128 a, float128 b STATUS_PARAM )
 | Arithmetic.
 *----------------------------------------------------------------------------*/
 
-flag float128_le( float128 a, float128 b STATUS_PARAM )
+int float128_le( float128 a, float128 b STATUS_PARAM )
 {
     flag aSign, bSign;
 
@@ -5061,7 +5072,7 @@ flag float128_le( float128 a, float128 b STATUS_PARAM )
 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
-flag float128_lt( float128 a, float128 b STATUS_PARAM )
+int float128_lt( float128 a, float128 b STATUS_PARAM )
 {
     flag aSign, bSign;
 
@@ -5094,7 +5105,7 @@ flag float128_lt( float128 a, float128 b STATUS_PARAM )
 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
-flag float128_eq_signaling( float128 a, float128 b STATUS_PARAM )
+int float128_eq_signaling( float128 a, float128 b STATUS_PARAM )
 {
 
     if (    (    ( extractFloat128Exp( a ) == 0x7FFF )
@@ -5121,7 +5132,7 @@ flag float128_eq_signaling( float128 a, float128 b STATUS_PARAM )
 | IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
-flag float128_le_quiet( float128 a, float128 b STATUS_PARAM )
+int float128_le_quiet( float128 a, float128 b STATUS_PARAM )
 {
     flag aSign, bSign;
 
@@ -5157,7 +5168,7 @@ flag float128_le_quiet( float128 a, float128 b STATUS_PARAM )
 | Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
-flag float128_lt_quiet( float128 a, float128 b STATUS_PARAM )
+int float128_lt_quiet( float128 a, float128 b STATUS_PARAM )
 {
     flag aSign, bSign;
 
@@ -5272,7 +5283,7 @@ unsigned int float64_to_uint32_round_to_zero( float64 a STATUS_PARAM )
 }
 
 #define COMPARE(s, nan_exp)                                                  \
-INLINE char float ## s ## _compare_internal( float ## s a, float ## s b,     \
+INLINE int float ## s ## _compare_internal( float ## s a, float ## s b,      \
                                       int is_quiet STATUS_PARAM )            \
 {                                                                            \
     flag aSign, bSign;                                                       \
@@ -5306,12 +5317,12 @@ INLINE char float ## s ## _compare_internal( float ## s a, float ## s b,     \
     }                                                                        \
 }                                                                            \
                                                                              \
-char float ## s ## _compare( float ## s a, float ## s b STATUS_PARAM )       \
+int float ## s ## _compare( float ## s a, float ## s b STATUS_PARAM )        \
 {                                                                            \
     return float ## s ## _compare_internal(a, b, 0 STATUS_VAR);              \
 }                                                                            \
                                                                              \
-char float ## s ## _compare_quiet( float ## s a, float ## s b STATUS_PARAM ) \
+int float ## s ## _compare_quiet( float ## s a, float ## s b STATUS_PARAM )  \
 {                                                                            \
     return float ## s ## _compare_internal(a, b, 1 STATUS_VAR);              \
 }
index fdc80f32dbd79e2d0ba31d5120ea3141d9c01c35..a326af83220b644d814069605ae707870deac169 100644 (file)
@@ -43,7 +43,7 @@ these four paragraphs for those parts of this code that are retained.
 | implementations of C, `flag', `uint8', and `int8' should all be `typedef'ed
 | to the same as `int'.
 *----------------------------------------------------------------------------*/
-typedef char flag;
+typedef uint8_t flag;
 typedef uint8_t uint8;
 typedef int8_t int8;
 typedef int uint16;
@@ -228,15 +228,16 @@ float32 float32_mul( float32, float32 STATUS_PARAM );
 float32 float32_div( float32, float32 STATUS_PARAM );
 float32 float32_rem( float32, float32 STATUS_PARAM );
 float32 float32_sqrt( float32 STATUS_PARAM );
-char float32_eq( float32, float32 STATUS_PARAM );
-char float32_le( float32, float32 STATUS_PARAM );
-char float32_lt( float32, float32 STATUS_PARAM );
-char float32_eq_signaling( float32, float32 STATUS_PARAM );
-char float32_le_quiet( float32, float32 STATUS_PARAM );
-char float32_lt_quiet( float32, float32 STATUS_PARAM );
-char float32_compare( float32, float32 STATUS_PARAM );
-char float32_compare_quiet( float32, float32 STATUS_PARAM );
-char float32_is_signaling_nan( float32 );
+int float32_eq( float32, float32 STATUS_PARAM );
+int float32_le( float32, float32 STATUS_PARAM );
+int float32_lt( float32, float32 STATUS_PARAM );
+int float32_eq_signaling( float32, float32 STATUS_PARAM );
+int float32_le_quiet( float32, float32 STATUS_PARAM );
+int float32_lt_quiet( float32, float32 STATUS_PARAM );
+int float32_compare( float32, float32 STATUS_PARAM );
+int float32_compare_quiet( float32, float32 STATUS_PARAM );
+int float32_is_signaling_nan( float32 );
+int float64_is_nan( float64 a );
 
 INLINE float32 float32_abs(float32 a)
 {
@@ -269,21 +270,22 @@ float128 float64_to_float128( float64 STATUS_PARAM );
 | Software IEC/IEEE double-precision operations.
 *----------------------------------------------------------------------------*/
 float64 float64_round_to_int( float64 STATUS_PARAM );
+float64 float64_trunc_to_int( float64 STATUS_PARAM );
 float64 float64_add( float64, float64 STATUS_PARAM );
 float64 float64_sub( float64, float64 STATUS_PARAM );
 float64 float64_mul( float64, float64 STATUS_PARAM );
 float64 float64_div( float64, float64 STATUS_PARAM );
 float64 float64_rem( float64, float64 STATUS_PARAM );
 float64 float64_sqrt( float64 STATUS_PARAM );
-char float64_eq( float64, float64 STATUS_PARAM );
-char float64_le( float64, float64 STATUS_PARAM );
-char float64_lt( float64, float64 STATUS_PARAM );
-char float64_eq_signaling( float64, float64 STATUS_PARAM );
-char float64_le_quiet( float64, float64 STATUS_PARAM );
-char float64_lt_quiet( float64, float64 STATUS_PARAM );
-char float64_compare( float64, float64 STATUS_PARAM );
-char float64_compare_quiet( float64, float64 STATUS_PARAM );
-char float64_is_signaling_nan( float64 );
+int float64_eq( float64, float64 STATUS_PARAM );
+int float64_le( float64, float64 STATUS_PARAM );
+int float64_lt( float64, float64 STATUS_PARAM );
+int float64_eq_signaling( float64, float64 STATUS_PARAM );
+int float64_le_quiet( float64, float64 STATUS_PARAM );
+int float64_lt_quiet( float64, float64 STATUS_PARAM );
+int float64_compare( float64, float64 STATUS_PARAM );
+int float64_compare_quiet( float64, float64 STATUS_PARAM );
+int float64_is_signaling_nan( float64 );
 
 INLINE float64 float64_abs(float64 a)
 {
@@ -320,13 +322,13 @@ floatx80 floatx80_mul( floatx80, floatx80 STATUS_PARAM );
 floatx80 floatx80_div( floatx80, floatx80 STATUS_PARAM );
 floatx80 floatx80_rem( floatx80, floatx80 STATUS_PARAM );
 floatx80 floatx80_sqrt( floatx80 STATUS_PARAM );
-char floatx80_eq( floatx80, floatx80 STATUS_PARAM );
-char floatx80_le( floatx80, floatx80 STATUS_PARAM );
-char floatx80_lt( floatx80, floatx80 STATUS_PARAM );
-char floatx80_eq_signaling( floatx80, floatx80 STATUS_PARAM );
-char floatx80_le_quiet( floatx80, floatx80 STATUS_PARAM );
-char floatx80_lt_quiet( floatx80, floatx80 STATUS_PARAM );
-char floatx80_is_signaling_nan( floatx80 );
+int floatx80_eq( floatx80, floatx80 STATUS_PARAM );
+int floatx80_le( floatx80, floatx80 STATUS_PARAM );
+int floatx80_lt( floatx80, floatx80 STATUS_PARAM );
+int floatx80_eq_signaling( floatx80, floatx80 STATUS_PARAM );
+int floatx80_le_quiet( floatx80, floatx80 STATUS_PARAM );
+int floatx80_lt_quiet( floatx80, floatx80 STATUS_PARAM );
+int floatx80_is_signaling_nan( floatx80 );
 
 INLINE floatx80 floatx80_abs(floatx80 a)
 {
@@ -367,13 +369,13 @@ float128 float128_mul( float128, float128 STATUS_PARAM );
 float128 float128_div( float128, float128 STATUS_PARAM );
 float128 float128_rem( float128, float128 STATUS_PARAM );
 float128 float128_sqrt( float128 STATUS_PARAM );
-char float128_eq( float128, float128 STATUS_PARAM );
-char float128_le( float128, float128 STATUS_PARAM );
-char float128_lt( float128, float128 STATUS_PARAM );
-char float128_eq_signaling( float128, float128 STATUS_PARAM );
-char float128_le_quiet( float128, float128 STATUS_PARAM );
-char float128_lt_quiet( float128, float128 STATUS_PARAM );
-char float128_is_signaling_nan( float128 );
+int float128_eq( float128, float128 STATUS_PARAM );
+int float128_le( float128, float128 STATUS_PARAM );
+int float128_lt( float128, float128 STATUS_PARAM );
+int float128_eq_signaling( float128, float128 STATUS_PARAM );
+int float128_le_quiet( float128, float128 STATUS_PARAM );
+int float128_lt_quiet( float128, float128 STATUS_PARAM );
+int float128_is_signaling_nan( float128 );
 
 INLINE float128 float128_abs(float128 a)
 {
index 6ad393f799780bc51bb353c3128791c669c56535..aeddc34745419ff3c482abbcf0443a7c94ab9ad3 100644 (file)
@@ -52,26 +52,30 @@ enum RSState {
     RS_GETLINE,
     RS_CHKSUM1,
     RS_CHKSUM2,
+    RS_SYSCALL,
 };
-/* XXX: This is not thread safe.  Do we care?  */
-static int gdbserver_fd = -1;
-
 typedef struct GDBState {
     CPUState *env; /* current CPU */
     enum RSState state; /* parsing state */
-    int fd;
     char line_buf[4096];
     int line_buf_index;
     int line_csum;
+    char last_packet[4100];
+    int last_packet_len;
 #ifdef CONFIG_USER_ONLY
+    int fd;
     int running_state;
+#else
+    CharDriverState *chr;
 #endif
 } GDBState;
 
 #ifdef CONFIG_USER_ONLY
+/* XXX: This is not thread safe.  Do we care?  */
+static int gdbserver_fd = -1;
+
 /* XXX: remove this hack.  */
 static GDBState gdbserver_state;
-#endif
 
 static int get_char(GDBState *s)
 {
@@ -91,9 +95,32 @@ static int get_char(GDBState *s)
     }
     return ch;
 }
+#endif
+
+/* GDB stub state for use by semihosting syscalls.  */
+static GDBState *gdb_syscall_state;
+static gdb_syscall_complete_cb gdb_current_syscall_cb;
+
+enum {
+    GDB_SYS_UNKNOWN,
+    GDB_SYS_ENABLED,
+    GDB_SYS_DISABLED,
+} gdb_syscall_mode;
+
+/* If gdb is connected when the first semihosting syscall occurs then use
+   remote gdb syscalls.  Otherwise use native file IO.  */
+int use_gdb_syscalls(void)
+{
+    if (gdb_syscall_mode == GDB_SYS_UNKNOWN) {
+        gdb_syscall_mode = (gdb_syscall_state ? GDB_SYS_ENABLED
+                                              : GDB_SYS_DISABLED);
+    }
+    return gdb_syscall_mode == GDB_SYS_ENABLED;
+}
 
 static void put_buffer(GDBState *s, const uint8_t *buf, int len)
 {
+#ifdef CONFIG_USER_ONLY
     int ret;
 
     while (len > 0) {
@@ -106,6 +133,9 @@ static void put_buffer(GDBState *s, const uint8_t *buf, int len)
             len -= ret;
         }
     }
+#else
+    qemu_chr_write(s->chr, buf, len);
+#endif
 }
 
 static inline int fromhex(int v)
@@ -154,33 +184,39 @@ static void hextomem(uint8_t *mem, const char *buf, int len)
 /* return -1 if error, 0 if OK */
 static int put_packet(GDBState *s, char *buf)
 {
-    char buf1[3];
-    int len, csum, ch, i;
+    int len, csum, i;
+    char *p;
 
 #ifdef DEBUG_GDB
     printf("reply='%s'\n", buf);
 #endif
 
     for(;;) {
-        buf1[0] = '$';
-        put_buffer(s, buf1, 1);
+        p = s->last_packet;
+        *(p++) = '$';
         len = strlen(buf);
-        put_buffer(s, buf, len);
+        memcpy(p, buf, len);
+        p += len;
         csum = 0;
         for(i = 0; i < len; i++) {
             csum += buf[i];
         }
-        buf1[0] = '#';
-        buf1[1] = tohex((csum >> 4) & 0xf);
-        buf1[2] = tohex((csum) & 0xf);
+        *(p++) = '#';
+        *(p++) = tohex((csum >> 4) & 0xf);
+        *(p++) = tohex((csum) & 0xf);
 
-        put_buffer(s, buf1, 3);
+        s->last_packet_len = p - s->last_packet;
+        put_buffer(s, s->last_packet, s->last_packet_len);
 
-        ch = get_char(s);
-        if (ch < 0)
+#ifdef CONFIG_USER_ONLY
+        i = get_char(s);
+        if (i < 0)
             return -1;
-        if (ch == '+')
+        if (i == '+')
             break;
+#else
+        break;
+#endif
     }
     return 0;
 }
@@ -434,6 +470,73 @@ static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
     ptr += 8 * 12 + 4;
     cpsr_write (env, tswapl(*(uint32_t *)ptr), 0xffffffff);
 }
+#elif defined (TARGET_M68K)
+static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
+{
+    int i;
+    uint8_t *ptr;
+    CPU_DoubleU u;
+
+    ptr = mem_buf;
+    /* D0-D7 */
+    for (i = 0; i < 8; i++) {
+        *(uint32_t *)ptr = tswapl(env->dregs[i]);
+        ptr += 4;
+    }
+    /* A0-A7 */
+    for (i = 0; i < 8; i++) {
+        *(uint32_t *)ptr = tswapl(env->aregs[i]);
+        ptr += 4;
+    }
+    *(uint32_t *)ptr = tswapl(env->sr);
+    ptr += 4;
+    *(uint32_t *)ptr = tswapl(env->pc);
+    ptr += 4;
+    /* F0-F7.  The 68881/68040 have 12-bit extended precision registers.
+       ColdFire has 8-bit double precision registers.  */
+    for (i = 0; i < 8; i++) {
+        u.d = env->fregs[i];
+        *(uint32_t *)ptr = tswap32(u.l.upper);
+        *(uint32_t *)ptr = tswap32(u.l.lower);
+    }
+    /* FP control regs (not implemented).  */
+    memset (ptr, 0, 3 * 4);
+    ptr += 3 * 4;
+
+    return ptr - mem_buf;
+}
+
+static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
+{
+    int i;
+    uint8_t *ptr;
+    CPU_DoubleU u;
+
+    ptr = mem_buf;
+    /* D0-D7 */
+    for (i = 0; i < 8; i++) {
+        env->dregs[i] = tswapl(*(uint32_t *)ptr);
+        ptr += 4;
+    }
+    /* A0-A7 */
+    for (i = 0; i < 8; i++) {
+        env->aregs[i] = tswapl(*(uint32_t *)ptr);
+        ptr += 4;
+    }
+    env->sr = tswapl(*(uint32_t *)ptr);
+    ptr += 4;
+    env->pc = tswapl(*(uint32_t *)ptr);
+    ptr += 4;
+    /* F0-F7.  The 68881/68040 have 12-bit extended precision registers.
+       ColdFire has 8-bit double precision registers.  */
+    for (i = 0; i < 8; i++) {
+        u.l.upper = tswap32(*(uint32_t *)ptr); 
+        u.l.lower = tswap32(*(uint32_t *)ptr);
+        env->fregs[i] = u.d;
+    }
+    /* FP control regs (not implemented).  */
+    ptr += 3 * 4;
+}
 #elif defined (TARGET_MIPS)
 static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
 {
@@ -465,11 +568,37 @@ static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
     *(uint32_t *)ptr = tswapl(env->PC);
     ptr += 4;
 
+#ifdef MIPS_USES_FPU
+    for (i = 0; i < 32; i++)
+      {
+        *(uint32_t *)ptr = tswapl(FPR_W (env, i));
+        ptr += 4;
+      }
+
+    *(uint32_t *)ptr = tswapl(env->fcr31);
+    ptr += 4;
+
+    *(uint32_t *)ptr = tswapl(env->fcr0);
+    ptr += 4;
+#endif
+
     /* 32 FP registers, fsr, fir, fp.  Not yet implemented.  */
+    /* what's 'fp' mean here?  */
 
     return ptr - mem_buf;
 }
 
+/* convert MIPS rounding mode in FCR31 to IEEE library */
+static unsigned int ieee_rm[] =
+  {
+    float_round_nearest_even,
+    float_round_to_zero,
+    float_round_up,
+    float_round_down
+  };
+#define RESTORE_ROUNDING_MODE \
+    set_float_rounding_mode(ieee_rm[env->fcr31 & 3], &env->fp_status)
+
 static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
 {
     int i;
@@ -499,6 +628,28 @@ static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
 
     env->PC = tswapl(*(uint32_t *)ptr);
     ptr += 4;
+
+#ifdef MIPS_USES_FPU
+    for (i = 0; i < 32; i++)
+      {
+       FPR_W (env, i) = tswapl(*(uint32_t *)ptr);
+        ptr += 4;
+      }
+
+    env->fcr31 = tswapl(*(uint32_t *)ptr) & 0x0183FFFF;
+    ptr += 4;
+
+    env->fcr0 = tswapl(*(uint32_t *)ptr);
+    ptr += 4;
+
+    /* set rounding mode */
+    RESTORE_ROUNDING_MODE;
+
+#ifndef CONFIG_SOFTFLOAT
+    /* no floating point exception for native float */
+    SET_FP_ENABLE(env->fcr31, 0);
+#endif
+#endif
 }
 #elif defined (TARGET_SH4)
 static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
@@ -626,6 +777,34 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf)
         vm_start();
 #endif
        return RS_IDLE;
+    case 'F':
+        {
+            target_ulong ret;
+            target_ulong err;
+
+            ret = strtoull(p, (char **)&p, 16);
+            if (*p == ',') {
+                p++;
+                err = strtoull(p, (char **)&p, 16);
+            } else {
+                err = 0;
+            }
+            if (*p == ',')
+                p++;
+            type = *p;
+            if (gdb_current_syscall_cb)
+                gdb_current_syscall_cb(s->env, ret, err);
+            if (type == 'C') {
+                put_packet(s, "T02");
+            } else {
+#ifdef CONFIG_USER_ONLY
+                s->running_state = 1;
+#else
+                vm_start();
+#endif
+            }
+        }
+        break;
     case 'g':
         reg_size = cpu_gdb_read_registers(env, mem_buf);
         memtohex(buf, mem_buf, reg_size);
@@ -695,7 +874,7 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf)
             goto breakpoint_error;
         }
         break;
-#ifdef CONFIG_USER_ONLY
+#ifdef CONFIG_LINUX_USER
     case 'q':
         if (strncmp(p, "Offsets", 7) == 0) {
             TaskState *ts = env->opaque;
@@ -726,6 +905,9 @@ static void gdb_vm_stopped(void *opaque, int reason)
     char buf[256];
     int ret;
 
+    if (s->state == RS_SYSCALL)
+        return;
+
     /* disable single step if it was enable */
     cpu_single_step(s->env, 0);
 
@@ -742,6 +924,60 @@ static void gdb_vm_stopped(void *opaque, int reason)
 }
 #endif
 
+/* Send a gdb syscall request.
+   This accepts limited printf-style format specifiers, specifically:
+    %x - target_ulong argument printed in hex.
+    %s - string pointer (target_ulong) and length (int) pair.  */
+void gdb_do_syscall(gdb_syscall_complete_cb cb, char *fmt, ...)
+{
+    va_list va;
+    char buf[256];
+    char *p;
+    target_ulong addr;
+    GDBState *s;
+
+    s = gdb_syscall_state;
+    if (!s)
+        return;
+    gdb_current_syscall_cb = cb;
+    s->state = RS_SYSCALL;
+#ifndef CONFIG_USER_ONLY
+    vm_stop(EXCP_DEBUG);
+#endif
+    s->state = RS_IDLE;
+    va_start(va, fmt);
+    p = buf;
+    *(p++) = 'F';
+    while (*fmt) {
+        if (*fmt == '%') {
+            fmt++;
+            switch (*fmt++) {
+            case 'x':
+                addr = va_arg(va, target_ulong);
+                p += sprintf(p, TARGET_FMT_lx, addr);
+                break;
+            case 's':
+                addr = va_arg(va, target_ulong);
+                p += sprintf(p, TARGET_FMT_lx "/%x", addr, va_arg(va, int));
+                break;
+            default:
+                fprintf(stderr, "gdbstub: Bad syscall format string '%s'\n",
+                        fmt - 1);
+                break;
+            }
+        } else {
+            *(p++) = *(fmt++);
+        }
+    }
+    va_end(va);
+    put_packet(s, buf);
+#ifdef CONFIG_USER_ONLY
+    gdb_handlesig(s->env, 0);
+#else
+    cpu_interrupt(s->env, CPU_INTERRUPT_EXIT);
+#endif
+}
+
 static void gdb_read_byte(GDBState *s, int ch)
 {
     CPUState *env = s->env;
@@ -749,6 +985,26 @@ static void gdb_read_byte(GDBState *s, int ch)
     char reply[1];
 
 #ifndef CONFIG_USER_ONLY
+    if (s->last_packet_len) {
+        /* Waiting for a response to the last packet.  If we see the start
+           of a new command then abandon the previous response.  */
+        if (ch == '-') {
+#ifdef DEBUG_GDB
+            printf("Got NACK, retransmitting\n");
+#endif
+            put_buffer(s, s->last_packet, s->last_packet_len);
+        }
+#ifdef DEBUG_GDB
+        else if (ch == '+')
+            printf("Got ACK\n");
+        else
+            printf("Got '%c' when expecting ACK/NACK\n", ch);
+#endif
+        if (ch == '+' || ch == '$')
+            s->last_packet_len = 0;
+        if (ch != '$')
+            return;
+    }
     if (vm_running) {
         /* when the CPU is running, we cannot do anything except stop
            it when receiving a char */
@@ -793,6 +1049,8 @@ static void gdb_read_byte(GDBState *s, int ch)
                 s->state = gdb_handle_packet(s, env, s->line_buf);
             }
             break;
+        default:
+            abort();
         }
     }
 }
@@ -857,29 +1115,6 @@ void gdb_exit(CPUState *env, int code)
   put_packet(s, buf);
 }
 
-#else
-static void gdb_read(void *opaque)
-{
-    GDBState *s = opaque;
-    int i, size;
-    uint8_t buf[4096];
-
-    size = recv(s->fd, buf, sizeof(buf), 0);
-    if (size < 0)
-        return;
-    if (size == 0) {
-        /* end of connection */
-        qemu_del_vm_stop_handler(gdb_vm_stopped, s);
-        qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
-        qemu_free(s);
-        vm_start();
-    } else {
-        for(i = 0; i < size; i++)
-            gdb_read_byte(s, buf[i]);
-    }
-}
-
-#endif
 
 static void gdb_accept(void *opaque)
 {
@@ -903,32 +1138,14 @@ static void gdb_accept(void *opaque)
     val = 1;
     setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
     
-#ifdef CONFIG_USER_ONLY
     s = &gdbserver_state;
     memset (s, 0, sizeof (GDBState));
-#else
-    s = qemu_mallocz(sizeof(GDBState));
-    if (!s) {
-        close(fd);
-        return;
-    }
-#endif
     s->env = first_cpu; /* XXX: allow to change CPU */
     s->fd = fd;
 
-#ifdef CONFIG_USER_ONLY
-    fcntl(fd, F_SETFL, O_NONBLOCK);
-#else
-    socket_set_nonblock(fd);
-
-    /* stop the VM */
-    vm_stop(EXCP_INTERRUPT);
+    gdb_syscall_state = s;
 
-    /* start handling I/O */
-    qemu_set_fd_handler(s->fd, gdb_read, NULL, s);
-    /* when the VM is stopped, the following callback is called */
-    qemu_add_vm_stop_handler(gdb_vm_stopped, s);
-#endif
+    fcntl(fd, F_SETFL, O_NONBLOCK);
 }
 
 static int gdbserver_open(int port)
@@ -959,9 +1176,6 @@ static int gdbserver_open(int port)
         perror("listen");
         return -1;
     }
-#ifndef CONFIG_USER_ONLY
-    socket_set_nonblock(fd);
-#endif
     return fd;
 }
 
@@ -971,10 +1185,67 @@ int gdbserver_start(int port)
     if (gdbserver_fd < 0)
         return -1;
     /* accept connections */
-#ifdef CONFIG_USER_ONLY
     gdb_accept (NULL);
+    return 0;
+}
 #else
-    qemu_set_fd_handler(gdbserver_fd, gdb_accept, NULL, NULL);
-#endif
+static int gdb_chr_can_recieve(void *opaque)
+{
+  return 1;
+}
+
+static void gdb_chr_recieve(void *opaque, const uint8_t *buf, int size)
+{
+    GDBState *s = opaque;
+    int i;
+
+    for (i = 0; i < size; i++) {
+        gdb_read_byte(s, buf[i]);
+    }
+}
+
+static void gdb_chr_event(void *opaque, int event)
+{
+    switch (event) {
+    case CHR_EVENT_RESET:
+        vm_stop(EXCP_INTERRUPT);
+        gdb_syscall_state = opaque;
+        break;
+    default:
+        break;
+    }
+}
+
+int gdbserver_start(CharDriverState *chr)
+{
+    GDBState *s;
+
+    if (!chr)
+        return -1;
+
+    s = qemu_mallocz(sizeof(GDBState));
+    if (!s) {
+        return -1;
+    }
+    s->env = first_cpu; /* XXX: allow to change CPU */
+    s->chr = chr;
+    qemu_chr_add_handlers(chr, gdb_chr_can_recieve, gdb_chr_recieve,
+                          gdb_chr_event, s);
+    qemu_add_vm_stop_handler(gdb_vm_stopped, s);
     return 0;
 }
+
+int gdbserver_start_port(int port)
+{
+    CharDriverState *chr;
+    char gdbstub_port_name[128];
+
+    snprintf(gdbstub_port_name, sizeof(gdbstub_port_name),
+             "tcp::%d,nowait,nodelay,server", port);
+    chr = qemu_chr_open(gdbstub_port_name);
+    if (!chr) 
+        return -EIO;
+    return gdbserver_start(chr);
+}
+
+#endif
index 7b42596f1524d6ad032040ed0b22876dc1052929..41ffc6d089e1edcb9cfc6641d20cf2b82ef57cd1 100644 (file)
@@ -3,10 +3,18 @@
 
 #define DEFAULT_GDBSTUB_PORT 1234
 
+typedef void (*gdb_syscall_complete_cb)(CPUState *env,
+                                        target_ulong ret, target_ulong err);
+
+void gdb_do_syscall(gdb_syscall_complete_cb cb, char *fmt, ...);
+int use_gdb_syscalls(void);
 #ifdef CONFIG_USER_ONLY
 int gdb_handlesig (CPUState *, int);
 void gdb_exit(CPUState *, int);
-#endif
 int gdbserver_start(int);
+#else
+int gdbserver_start(CharDriverState *chr);
+int gdbserver_start_port(int port);
+#endif
 
 #endif
diff --git a/tools/ioemu/hostregs_helper.h b/tools/ioemu/hostregs_helper.h
new file mode 100644 (file)
index 0000000..4fdf8ad
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ *  Save/restore host registrs.
+ *
+ *  Copyright (c) 2007 CodeSourcery
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* The GCC global register vairable extension is used to reserve some
+   host registers for use by dyngen.  However only the core parts of the
+   translation engine are compiled with these settings.  We must manually
+   save/restore these registers when called from regular code.
+   It is not sufficient to save/restore T0 et. al. as these may be declared
+   with a datatype smaller than the actual register.  */
+
+#if defined(DECLARE_HOST_REGS)
+
+#define DO_REG(REG)                                    \
+    register host_reg_t reg_AREG##REG asm(AREG##REG);  \
+    volatile host_reg_t saved_AREG##REG;
+
+#elif defined(SAVE_HOST_REGS)
+
+#define DO_REG(REG)                                    \
+    __asm__ __volatile__ ("" : "=r" (reg_AREG##REG));  \
+    saved_AREG##REG = reg_AREG##REG;
+
+#else
+
+#define DO_REG(REG)                                     \
+    reg_AREG##REG = saved_AREG##REG;                   \
+    __asm__ __volatile__ ("" : : "r" (reg_AREG##REG));
+
+#endif
+
+#ifdef AREG0
+DO_REG(0)
+#endif
+
+#ifdef AREG1
+DO_REG(1)
+#endif
+
+#ifdef AREG2
+DO_REG(2)
+#endif
+
+#ifdef AREG3
+DO_REG(3)
+#endif
+
+#ifdef AREG4
+DO_REG(4)
+#endif
+
+#ifdef AREG5
+DO_REG(5)
+#endif
+
+#ifdef AREG6
+DO_REG(6)
+#endif
+
+#ifdef AREG7
+DO_REG(7)
+#endif
+
+#ifdef AREG8
+DO_REG(8)
+#endif
+
+#ifdef AREG9
+DO_REG(9)
+#endif
+
+#ifdef AREG10
+DO_REG(10)
+#endif
+
+#ifdef AREG11
+DO_REG(11)
+#endif
+
+#undef SAVE_HOST_REGS
+#undef DECLARE_HOST_REGS
+#undef DO_REG
index 600ce46b85084dedafb046662d2890ad35a30106..b74f8ad9b2172acc0aa7f5c27be28f887c111434 100644 (file)
@@ -1,89 +1,98 @@
-/acpi-dsdt.dsl/1.3/Wed Jun 14 18:17:04 2006//Trelease_0_8_2
-/acpi-dsdt.hex/1.3/Wed Jun 14 18:17:04 2006//Trelease_0_8_2
-/acpi.c/1.5/Wed Jun 14 18:17:04 2006//Trelease_0_8_2
-/adb.c/1.6/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/adlib.c/1.6/Sun Aug  6 01:03:50 2006//Trelease_0_8_2
-/apb_pci.c/1.1/Sat May 13 16:11:23 2006//Trelease_0_8_2
-/apic.c/1.9/Sun Aug  6 01:03:50 2006//Trelease_0_8_2
-/arm_boot.c/1.1/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/arm_pic.c/1.1/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/arm_pic.h/1.1/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/arm_timer.c/1.1/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/cdrom.c/1.1/Thu May 25 23:58:51 2006//Trelease_0_8_2
-/cirrus_vga.c/1.21/Sun Aug  6 00:55:02 2006//Trelease_0_8_2
-/cirrus_vga_rop.h/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/cirrus_vga_rop2.h/1.7/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/cuda.c/1.11/Sun Aug  6 01:03:50 2006//Trelease_0_8_2
-/dma.c/1.14/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/es1370.c/1.6/Sun Aug  6 01:03:50 2006//Trelease_0_8_2
-/esp.c/1.12/Sun Aug  6 01:03:50 2006//Trelease_0_8_2
-/fdc.c/1.18/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/fmopl.c/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/fmopl.h/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/grackle_pci.c/1.1/Sat May 13 16:11:23 2006//Trelease_0_8_2
-/heathrow_pic.c/1.2/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/i8254.c/1.8/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/i8259.c/1.19/Sun Aug  6 01:03:50 2006//Trelease_0_8_2
-/ide.c/1.45/Sun Aug  6 01:03:50 2006//Trelease_0_8_2
-/integratorcp.c/1.9/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/iommu.c/1.6/Sun Aug  6 00:55:03 2006//Trelease_0_8_2
-/lance.c/1.7/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/lsi53c895a.c/1.1/Tue May 30 01:48:12 2006//Trelease_0_8_2
-/m48t59.c/1.8/Sun Aug  6 01:03:50 2006//Trelease_0_8_2
-/m48t59.h/1.5/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/mc146818rtc.c/1.6/Sun Aug  6 00:55:02 2006//Trelease_0_8_2
-/mips_r4k.c/1.18/Sun Aug  6 01:03:50 2006//Trelease_0_8_2
-/ne2000.c/1.20/Sun Aug  6 01:03:50 2006//Trelease_0_8_2
-/openpic.c/1.9/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/parallel.c/1.4/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/pc.c/1.60/Sun Aug  6 01:03:50 2006//Trelease_0_8_2
-/pci.c/1.27/Sun Aug  6 01:03:50 2006//Trelease_0_8_2
-/pci_host.h/1.1/Sat May 13 16:11:23 2006//Trelease_0_8_2
-/pckbd.c/1.15/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/pcnet.c/1.4/Fri Jul 14 09:40:02 2006//Trelease_0_8_2
-/pcspk.c/1.2/Sun Aug  6 01:03:51 2006//Trelease_0_8_2
-/pflash_cfi02.c/1.2/Tue Jul  4 09:46:31 2006//Trelease_0_8_2
-/piix_pci.c/1.1/Sat May 13 16:11:23 2006//Trelease_0_8_2
-/pl011.c/1.1/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/pl050.c/1.2/Sun Aug  6 01:03:51 2006//Trelease_0_8_2
-/pl080.c/1.1/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/pl110.c/1.6/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/pl110_template.h/1.2/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/pl190.c/1.1/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/ppc.c/1.9/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/ppc_chrp.c/1.23/Sun Aug  6 01:03:51 2006//Trelease_0_8_2
-/ppc_prep.c/1.27/Sun Aug  6 01:03:51 2006//Trelease_0_8_2
-/prep_pci.c/1.1/Sat May 13 16:11:23 2006//Trelease_0_8_2
-/ps2.c/1.4/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/rtl8139.c/1.4/Sun Aug  6 01:03:51 2006//Trelease_0_8_2
-/sb16.c/1.22/Sun Aug  6 01:03:51 2006//Trelease_0_8_2
-/scsi-disk.c/1.7/Sun Jun  4 11:39:07 2006//Trelease_0_8_2
-/serial.c/1.12/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/sh7750.c/1.2/Sun Aug  6 01:03:51 2006//Trelease_0_8_2
-/sh7750_regnames.c/1.1/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/sh7750_regnames.h/1.1/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/sh7750_regs.h/1.1/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/shix.c/1.1/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/slavio_intctl.c/1.7/Sun Aug  6 01:03:51 2006//Trelease_0_8_2
-/slavio_misc.c/1.3/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/slavio_serial.c/1.6/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/slavio_timer.c/1.4/Sun Aug  6 01:03:51 2006//Trelease_0_8_2
-/smc91c111.c/1.3/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/sun4m.c/1.18/Sun Aug  6 01:03:51 2006//Trelease_0_8_2
-/sun4u.c/1.11/Sun Aug  6 01:03:51 2006//Trelease_0_8_2
-/tc58128.c/1.1/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/tcx.c/1.7/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/unin_pci.c/1.1/Sat May 13 16:11:23 2006//Trelease_0_8_2
-/usb-hid.c/1.5/Sun Aug  6 01:03:51 2006//Trelease_0_8_2
-/usb-hub.c/1.8/Sun Aug  6 01:03:51 2006//Trelease_0_8_2
-/usb-msd.c/1.4/Wed Jul 19 18:06:15 2006//Trelease_0_8_2
-/usb-ohci.c/1.3/Thu May 25 23:37:07 2006//Trelease_0_8_2
-/usb-uhci.c/1.11/Sun Aug  6 01:03:51 2006//Trelease_0_8_2
-/usb.c/1.8/Sun Aug  6 01:03:51 2006//Trelease_0_8_2
-/usb.h/1.9/Sun Aug  6 01:03:51 2006//Trelease_0_8_2
-/versatile_pci.c/1.1/Sat May 13 16:11:23 2006//Trelease_0_8_2
-/versatilepb.c/1.5/Sun Aug  6 01:03:51 2006//Trelease_0_8_2
-/vga.c/1.44/Sun Aug  6 01:03:51 2006//Trelease_0_8_2
-/vga_int.h/1.7/Sun Aug  6 01:03:51 2006//Trelease_0_8_2
-/vga_template.h/1.13/Sun Aug  6 01:03:51 2006//Trelease_0_8_2
+/acpi.c/1.8/Thu May  3 17:18:00 2007//Trelease_0_9_0
+/adb.c/1.7/Thu May  3 17:18:00 2007//Trelease_0_9_0
+/adlib.c/1.6/Fri Jan  5 14:34:35 2007//Trelease_0_9_0
+/apb_pci.c/1.4/Thu May  3 17:18:00 2007//Trelease_0_9_0
+/apic.c/1.12/Thu May  3 17:18:00 2007//Trelease_0_9_0
+/arm_boot.c/1.3/Thu May  3 17:18:00 2007//Trelease_0_9_0
+/arm_gic.c/1.3/Tue Jan  2 19:33:15 2007//Trelease_0_9_0
+/arm_pic.c/1.1/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/arm_pic.h/1.1/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/arm_sysctl.c/1.1/Sat Sep 23 17:40:58 2006//Trelease_0_9_0
+/arm_timer.c/1.2/Thu May  3 17:18:00 2007//Trelease_0_9_0
+/cdrom.c/1.1/Fri Jan  5 14:34:35 2007//Trelease_0_9_0
+/cirrus_vga.c/1.23/Thu May  3 17:18:00 2007//Trelease_0_9_0
+/cirrus_vga_rop.h/1.1/Thu May  3 17:17:34 2007//Trelease_0_9_0
+/cirrus_vga_rop2.h/1.7/Thu May  3 17:17:34 2007//Trelease_0_9_0
+/cs4231.c/1.1/Sun Sep 10 19:25:12 2006//Trelease_0_9_0
+/cuda.c/1.11/Fri Jan  5 14:34:35 2007//Trelease_0_9_0
+/dma.c/1.14/Thu May  3 17:17:33 2007//Trelease_0_9_0
+/es1370.c/1.6/Fri Jan  5 14:34:35 2007//Trelease_0_9_0
+/esp.c/1.18/Thu May  3 17:18:00 2007//Trelease_0_9_0
+/fdc.c/1.21/Thu May  3 17:18:00 2007//Trelease_0_9_0
+/fmopl.c/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
+/fmopl.h/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
+/grackle_pci.c/1.3/Thu May  3 17:18:00 2007//Trelease_0_9_0
+/gt64xxx.c/1.4/Wed Jan 31 12:02:12 2007//Trelease_0_9_0
+/heathrow_pic.c/1.2/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/i8254.c/1.8/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/i8259.c/1.20/Thu May  3 17:18:00 2007//Trelease_0_9_0
+/ide.c/1.53/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/integratorcp.c/1.11/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/iommu.c/1.8/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/isa_mmio.c/1.1/Mon Sep 18 01:15:29 2006//Trelease_0_9_0
+/lsi53c895a.c/1.3/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/m48t59.c/1.8/Fri Jan  5 14:34:35 2007//Trelease_0_9_0
+/m48t59.h/1.5/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/mc146818rtc.c/1.7/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/mips_int.c/1.1/Wed Jan 24 01:47:51 2007//Trelease_0_9_0
+/mips_malta.c/1.7/Wed Jan 31 11:48:27 2007//Trelease_0_9_0
+/mips_r4k.c/1.33/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/mips_timer.c/1.2/Wed Jan 24 01:47:51 2007//Trelease_0_9_0
+/ne2000.c/1.23/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/openpic.c/1.9/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/parallel.c/1.4/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/pc.c/1.69/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/pci.c/1.34/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/pci_host.h/1.1/Fri Jan  5 14:34:35 2007//Trelease_0_9_0
+/pckbd.c/1.15/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/pcnet.c/1.8/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/pcspk.c/1.2/Fri Jan  5 14:34:35 2007//Trelease_0_9_0
+/pflash_cfi02.c/1.3/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/piix_pci.c/1.9/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/pl011.c/1.2/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/pl050.c/1.2/Fri Jan  5 14:34:35 2007//Trelease_0_9_0
+/pl080.c/1.2/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/pl110.c/1.7/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/pl110_template.h/1.3/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/pl190.c/1.1/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/ppc.c/1.10/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/ppc_chrp.c/1.26/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/ppc_prep.c/1.29/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/prep_pci.c/1.3/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/ps2.c/1.5/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/realview.c/1.3/Tue Jan 16 18:54:31 2007//Trelease_0_9_0
+/rtl8139.c/1.6/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/sb16.c/1.22/Fri Jan  5 14:34:35 2007//Trelease_0_9_0
+/scsi-disk.c/1.13/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/serial.c/1.14/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/sh7750.c/1.3/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/sh7750_regnames.c/1.1/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/sh7750_regnames.h/1.1/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/sh7750_regs.h/1.1/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/shix.c/1.1/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/slavio_intctl.c/1.7/Fri Jan  5 14:34:35 2007//Trelease_0_9_0
+/slavio_misc.c/1.4/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/slavio_serial.c/1.11/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/slavio_timer.c/1.4/Fri Jan  5 14:34:35 2007//Trelease_0_9_0
+/smbus.h/1.1/Fri Feb  2 03:13:18 2007//Trelease_0_9_0
+/smbus_eeprom.c/1.1/Fri Feb  2 03:13:18 2007//Trelease_0_9_0
+/smc91c111.c/1.5/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/sparc32_dma.c/1.2/Sun Sep  3 19:48:17 2006//Trelease_0_9_0
+/sun4m.c/1.24/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/sun4u.c/1.12/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/tc58128.c/1.1/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/tcx.c/1.10/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/unin_pci.c/1.4/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/usb-hid.c/1.7/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/usb-hub.c/1.9/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/usb-msd.c/1.7/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/usb-ohci.c/1.4/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/usb-uhci.c/1.13/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/usb.c/1.9/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/usb.h/1.10/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/versatile_pci.c/1.4/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/versatilepb.c/1.8/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/vga.c/1.48/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/vga_int.h/1.10/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/vga_template.h/1.13/Fri Jan  5 14:34:35 2007//Trelease_0_9_0
 D
index bd48d406fa1b16a1721b34dc4bb6979acc4274da..eed9f4a4fb93e992c8c20b591822041f09711c7e 100644 (file)
@@ -1 +1 @@
-Nrelease_0_8_2
+Nrelease_0_9_0
diff --git a/tools/ioemu/hw/acpi-dsdt.dsl b/tools/ioemu/hw/acpi-dsdt.dsl
deleted file mode 100644 (file)
index fc4081f..0000000
+++ /dev/null
@@ -1,559 +0,0 @@
-/*
- * QEMU ACPI DSDT ASL definition
- * 
- * Copyright (c) 2006 Fabrice Bellard
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2 as published by the Free Software Foundation.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-DefinitionBlock (
-    "acpi-dsdt.aml",    // Output Filename
-    "DSDT",             // Signature
-    0x01,               // DSDT Compliance Revision
-    "QEMU",             // OEMID
-    "QEMUDSDT",         // TABLE ID
-    0x1                 // OEM Revision
-    )
-{
-    Scope (\)
-    {
-        /* CMOS memory access */
-        OperationRegion (CMS, SystemIO, 0x70, 0x02)
-        Field (CMS, ByteAcc, NoLock, Preserve)
-        {
-            CMSI,   8, 
-            CMSD,   8
-        }
-        Method (CMRD, 1, NotSerialized)
-        {
-            Store (Arg0, CMSI)
-            Store (CMSD, Local0)
-            Return (Local0)
-        }
-
-        /* Debug Output */
-        OperationRegion (DBG, SystemIO, 0xb044, 0x04)
-        Field (DBG, DWordAcc, NoLock, Preserve)
-        {
-            DBGL,   32, 
-        }
-    }
-
-
-    /* PCI Bus definition */
-    Scope(\_SB) {
-        Device(PCI0) {
-            Name (_HID, EisaId ("PNP0A03"))
-            Name (_ADR, 0x00)
-            Name (_UID, 1)
-            Name(_PRT, Package() {
-                /* PCI IRQ routing table, example from ACPI 2.0a specification,
-                   section 6.2.8.1 */
-                /* Note: we provide the same info as the PCI routing
-                   table of the Bochs BIOS */
-                   
-                // PCI Slot 0
-                Package() {0x0000ffff, 0, LNKD, 0}, 
-                Package() {0x0000ffff, 1, LNKA, 0}, 
-                Package() {0x0000ffff, 2, LNKB, 0}, 
-                Package() {0x0000ffff, 3, LNKC, 0}, 
-
-                // PCI Slot 1
-                Package() {0x0001ffff, 0, LNKA, 0}, 
-                Package() {0x0001ffff, 1, LNKB, 0}, 
-                Package() {0x0001ffff, 2, LNKC, 0}, 
-                Package() {0x0001ffff, 3, LNKD, 0}, 
-                
-                // PCI Slot 2
-                Package() {0x0002ffff, 0, LNKB, 0}, 
-                Package() {0x0002ffff, 1, LNKC, 0}, 
-                Package() {0x0002ffff, 2, LNKD, 0}, 
-                Package() {0x0002ffff, 3, LNKA, 0}, 
-
-                // PCI Slot 3
-                Package() {0x0003ffff, 0, LNKC, 0}, 
-                Package() {0x0003ffff, 1, LNKD, 0}, 
-                Package() {0x0003ffff, 2, LNKA, 0}, 
-                Package() {0x0003ffff, 3, LNKB, 0}, 
-
-                // PCI Slot 4
-                Package() {0x0004ffff, 0, LNKD, 0}, 
-                Package() {0x0004ffff, 1, LNKA, 0}, 
-                Package() {0x0004ffff, 2, LNKB, 0}, 
-                Package() {0x0004ffff, 3, LNKC, 0}, 
-
-                // PCI Slot 5
-                Package() {0x0005ffff, 0, LNKA, 0}, 
-                Package() {0x0005ffff, 1, LNKB, 0}, 
-                Package() {0x0005ffff, 2, LNKC, 0}, 
-                Package() {0x0005ffff, 3, LNKD, 0}, 
-            })
-
-            Method (_CRS, 0, NotSerialized)
-            {
-            Name (MEMP, ResourceTemplate ()
-            {
-                WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode,
-                    0x0000,             // Address Space Granularity
-                    0x0000,             // Address Range Minimum
-                    0x00FF,             // Address Range Maximum
-                    0x0000,             // Address Translation Offset
-                    0x0100,             // Address Length
-                    ,, )
-                IO (Decode16,
-                    0x0CF8,             // Address Range Minimum
-                    0x0CF8,             // Address Range Maximum
-                    0x01,               // Address Alignment
-                    0x08,               // Address Length
-                    )
-                WordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
-                    0x0000,             // Address Space Granularity
-                    0x0000,             // Address Range Minimum
-                    0x0CF7,             // Address Range Maximum
-                    0x0000,             // Address Translation Offset
-                    0x0CF8,             // Address Length
-                    ,, , TypeStatic)
-                WordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
-                    0x0000,             // Address Space Granularity
-                    0x0D00,             // Address Range Minimum
-                    0xFFFF,             // Address Range Maximum
-                    0x0000,             // Address Translation Offset
-                    0xF300,             // Address Length
-                    ,, , TypeStatic)
-                DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
-                    0x00000000,         // Address Space Granularity
-                    0x000A0000,         // Address Range Minimum
-                    0x000BFFFF,         // Address Range Maximum
-                    0x00000000,         // Address Translation Offset
-                    0x00020000,         // Address Length
-                    ,, , AddressRangeMemory, TypeStatic)
-                DWordMemory (ResourceProducer, PosDecode, MinNotFixed, MaxFixed, NonCacheable, ReadWrite,
-                    0x00000000,         // Address Space Granularity
-                    0x00000000,         // Address Range Minimum
-                    0xFEBFFFFF,         // Address Range Maximum
-                    0x00000000,         // Address Translation Offset
-                    0x00000000,         // Address Length
-                    ,, MEMF, AddressRangeMemory, TypeStatic)
-            })
-                CreateDWordField (MEMP, \_SB.PCI0._CRS.MEMF._MIN, PMIN)
-                CreateDWordField (MEMP, \_SB.PCI0._CRS.MEMF._MAX, PMAX)
-                CreateDWordField (MEMP, \_SB.PCI0._CRS.MEMF._LEN, PLEN)
-                /* compute available RAM */
-                Add(CMRD(0x34), ShiftLeft(CMRD(0x35), 8), Local0)
-                ShiftLeft(Local0, 16, Local0)
-                Add(Local0, 0x1000000, Local0)
-                /* update field of last region */
-                Store(Local0, PMIN)
-                Subtract (PMAX, PMIN, PLEN)
-                Increment (PLEN)
-                Return (MEMP)
-            }
-        }
-    }
-
-    Scope(\_SB.PCI0) {
-
-       /* PIIX3 ISA bridge */
-        Device (ISA) {
-            Name (_ADR, 0x00010000)
-        
-            /* PIIX PCI to ISA irq remapping */
-            OperationRegion (P40C, PCI_Config, 0x60, 0x04)
-
-
-            /* Keyboard seems to be important for WinXP install */
-            Device (KBD)
-            {
-                Name (_HID, EisaId ("PNP0303"))
-                Method (_STA, 0, NotSerialized)
-                {
-                    Return (0x0f)
-                }
-
-                Method (_CRS, 0, NotSerialized)
-                {
-                     Name (TMP, ResourceTemplate ()
-                     {
-                    IO (Decode16,
-                        0x0060,             // Address Range Minimum
-                        0x0060,             // Address Range Maximum
-                        0x01,               // Address Alignment
-                        0x01,               // Address Length
-                        )
-                    IO (Decode16,
-                        0x0064,             // Address Range Minimum
-                        0x0064,             // Address Range Maximum
-                        0x01,               // Address Alignment
-                        0x01,               // Address Length
-                        )
-                    IRQNoFlags ()
-                        {1}
-                    })
-                    Return (TMP)
-                }
-            }
-
-           /* PS/2 mouse */
-            Device (MOU) 
-            {
-                Name (_HID, EisaId ("PNP0F13"))
-                Method (_STA, 0, NotSerialized)
-                {
-                    Return (0x0f)
-                }
-
-                Method (_CRS, 0, NotSerialized)
-                {
-                    Name (TMP, ResourceTemplate ()
-                    {
-                         IRQNoFlags () {12}
-                    })
-                    Return (TMP)
-                }
-            }
-
-           /* PS/2 floppy controller */
-           Device (FDC0)
-           {
-               Name (_HID, EisaId ("PNP0700"))
-               Method (_STA, 0, NotSerialized)
-               {
-                   Return (0x0F)
-               }
-               Method (_CRS, 0, NotSerialized)
-               {
-                   Name (BUF0, ResourceTemplate ()
-                    {
-                        IO (Decode16, 0x03F2, 0x03F2, 0x00, 0x04)
-                        IO (Decode16, 0x03F7, 0x03F7, 0x00, 0x01)
-                        IRQNoFlags () {6}
-                        DMA (Compatibility, NotBusMaster, Transfer8) {2}
-                    })
-                   Return (BUF0)
-               }
-           }
-
-           /* Parallel port */
-           Device (LPT)
-           {
-               Name (_HID, EisaId ("PNP0400"))
-               Method (_STA, 0, NotSerialized)
-               {
-                   Store (\_SB.PCI0.PX13.DRSA, Local0)
-                   And (Local0, 0x80000000, Local0)
-                   If (LEqual (Local0, 0))
-                   {
-                       Return (0x00)
-                   }
-                   Else
-                   {
-                       Return (0x0F)
-                   }
-               }
-               Method (_CRS, 0, NotSerialized)
-               {
-                   Name (BUF0, ResourceTemplate ()
-                    {
-                       IO (Decode16, 0x0378, 0x0378, 0x08, 0x08)
-                       IRQNoFlags () {7}
-                   })
-                   Return (BUF0)
-               }
-           }
-
-           /* Serial Ports */
-           Device (COM1)
-           {
-               Name (_HID, EisaId ("PNP0501"))
-               Name (_UID, 0x01)
-               Method (_STA, 0, NotSerialized)
-               {
-                   Store (\_SB.PCI0.PX13.DRSC, Local0)
-                   And (Local0, 0x08000000, Local0)
-                   If (LEqual (Local0, 0))
-                   {
-                       Return (0x00)
-                   }
-                   Else
-                   {
-                       Return (0x0F)
-                   }
-               }
-               Method (_CRS, 0, NotSerialized)
-               {
-                   Name (BUF0, ResourceTemplate ()
-                    {
-                       IO (Decode16, 0x03F8, 0x03F8, 0x00, 0x08)
-                       IRQNoFlags () {4}
-                   })
-                   Return (BUF0)
-               }
-           }
-
-           Device (COM2)
-           {
-               Name (_HID, EisaId ("PNP0501"))
-               Name (_UID, 0x02)
-               Method (_STA, 0, NotSerialized)
-               {
-                   Store (\_SB.PCI0.PX13.DRSC, Local0)
-                   And (Local0, 0x80000000, Local0)
-                   If (LEqual (Local0, 0))
-                   {
-                       Return (0x00)
-                   }
-                   Else
-                   {
-                       Return (0x0F)
-                   }
-               }
-               Method (_CRS, 0, NotSerialized)
-               {
-                   Name (BUF0, ResourceTemplate ()
-                    {
-                       IO (Decode16, 0x02F8, 0x02F8, 0x00, 0x08)
-                       IRQNoFlags () {3}
-                   })
-                   Return (BUF0)
-               }
-           }
-        }
-
-       /* PIIX4 PM */
-        Device (PX13) {
-           Name (_ADR, 0x00010003)
-
-           OperationRegion (P13C, PCI_Config, 0x5c, 0x24)
-           Field (P13C, DWordAcc, NoLock, Preserve)
-           {
-               DRSA, 32,
-               DRSB, 32,
-               DRSC, 32,
-               DRSE, 32,
-               DRSF, 32,
-               DRSG, 32,
-               DRSH, 32,
-               DRSI, 32,
-               DRSJ, 32
-           }
-       }
-    }
-
-    /* PCI IRQs */
-    Scope(\_SB) {
-         Field (\_SB.PCI0.ISA.P40C, ByteAcc, NoLock, Preserve)
-         {
-             PRQ0,   8, 
-             PRQ1,   8, 
-             PRQ2,   8, 
-             PRQ3,   8
-         }
-
-        Device(LNKA){
-                Name(_HID, EISAID("PNP0C0F"))     // PCI interrupt link
-                Name(_UID, 1)
-                Name(_PRS, ResourceTemplate(){
-                    IRQ (Level, ActiveLow, Shared)
-                        {3,4,5,6,7,9,10,11,12}
-                })
-                Method (_STA, 0, NotSerialized)
-                {
-                    Store (0x0B, Local0)
-                    If (And (0x80, PRQ0, Local1))
-                    {
-                         Store (0x09, Local0)
-                    }
-                    Return (Local0)
-                }
-                Method (_DIS, 0, NotSerialized)
-                {
-                    Or (PRQ0, 0x80, PRQ0)
-                }
-                Method (_CRS, 0, NotSerialized)
-                {
-                    Name (PRR0, ResourceTemplate ()
-                    {
-                        IRQ (Level, ActiveLow, Shared)
-                            {1}
-                    })
-                    CreateWordField (PRR0, 0x01, TMP)
-                    Store (PRQ0, Local0)
-                    If (LLess (Local0, 0x80))
-                    {
-                        ShiftLeft (One, Local0, TMP)
-                    }
-                    Else
-                    {
-                        Store (Zero, TMP)
-                    }
-                    Return (PRR0)
-                }
-                Method (_SRS, 1, NotSerialized)
-                {
-                    CreateWordField (Arg0, 0x01, TMP)
-                    FindSetRightBit (TMP, Local0)
-                    Decrement (Local0)
-                    Store (Local0, PRQ0)
-                }
-        }
-        Device(LNKB){
-                Name(_HID, EISAID("PNP0C0F"))     // PCI interrupt link
-                Name(_UID, 2)
-                Name(_PRS, ResourceTemplate(){
-                    IRQ (Level, ActiveLow, Shared)
-                        {3,4,5,6,7,9,10,11,12}
-                })
-                Method (_STA, 0, NotSerialized)
-                {
-                    Store (0x0B, Local0)
-                    If (And (0x80, PRQ1, Local1))
-                    {
-                         Store (0x09, Local0)
-                    }
-                    Return (Local0)
-                }
-                Method (_DIS, 0, NotSerialized)
-                {
-                    Or (PRQ1, 0x80, PRQ1)
-                }
-                Method (_CRS, 0, NotSerialized)
-                {
-                    Name (PRR0, ResourceTemplate ()
-                    {
-                        IRQ (Level, ActiveLow, Shared)
-                            {1}
-                    })
-                    CreateWordField (PRR0, 0x01, TMP)
-                    Store (PRQ1, Local0)
-                    If (LLess (Local0, 0x80))
-                    {
-                        ShiftLeft (One, Local0, TMP)
-                    }
-                    Else
-                    {
-                        Store (Zero, TMP)
-                    }
-                    Return (PRR0)
-                }
-                Method (_SRS, 1, NotSerialized)
-                {
-                    CreateWordField (Arg0, 0x01, TMP)
-                    FindSetRightBit (TMP, Local0)
-                    Decrement (Local0)
-                    Store (Local0, PRQ1)
-                }
-        }
-        Device(LNKC){
-                Name(_HID, EISAID("PNP0C0F"))     // PCI interrupt link
-                Name(_UID, 3)
-                Name(_PRS, ResourceTemplate(){
-                    IRQ (Level, ActiveLow, Shared)
-                        {3,4,5,6,7,9,10,11,12}
-                })
-                Method (_STA, 0, NotSerialized)
-                {
-                    Store (0x0B, Local0)
-                    If (And (0x80, PRQ2, Local1))
-                    {
-                         Store (0x09, Local0)
-                    }
-                    Return (Local0)
-                }
-                Method (_DIS, 0, NotSerialized)
-                {
-                    Or (PRQ2, 0x80, PRQ2)
-                }
-                Method (_CRS, 0, NotSerialized)
-                {
-                    Name (PRR0, ResourceTemplate ()
-                    {
-                        IRQ (Level, ActiveLow, Shared)
-                            {1}
-                    })
-                    CreateWordField (PRR0, 0x01, TMP)
-                    Store (PRQ2, Local0)
-                    If (LLess (Local0, 0x80))
-                    {
-                        ShiftLeft (One, Local0, TMP)
-                    }
-                    Else
-                    {
-                        Store (Zero, TMP)
-                    }
-                    Return (PRR0)
-                }
-                Method (_SRS, 1, NotSerialized)
-                {
-                    CreateWordField (Arg0, 0x01, TMP)
-                    FindSetRightBit (TMP, Local0)
-                    Decrement (Local0)
-                    Store (Local0, PRQ2)
-                }
-        }
-        Device(LNKD){
-                Name(_HID, EISAID("PNP0C0F"))     // PCI interrupt link
-                Name(_UID, 4)
-                Name(_PRS, ResourceTemplate(){
-                    IRQ (Level, ActiveLow, Shared)
-                        {3,4,5,6,7,9,10,11,12}
-                })
-                Method (_STA, 0, NotSerialized)
-                {
-                    Store (0x0B, Local0)
-                    If (And (0x80, PRQ3, Local1))
-                    {
-                         Store (0x09, Local0)
-                    }
-                    Return (Local0)
-                }
-                Method (_DIS, 0, NotSerialized)
-                {
-                    Or (PRQ3, 0x80, PRQ3)
-                }
-                Method (_CRS, 0, NotSerialized)
-                {
-                    Name (PRR0, ResourceTemplate ()
-                    {
-                        IRQ (Level, ActiveLow, Shared)
-                            {1}
-                    })
-                    CreateWordField (PRR0, 0x01, TMP)
-                    Store (PRQ3, Local0)
-                    If (LLess (Local0, 0x80))
-                    {
-                        ShiftLeft (One, Local0, TMP)
-                    }
-                    Else
-                    {
-                        Store (Zero, TMP)
-                    }
-                    Return (PRR0)
-                }
-                Method (_SRS, 1, NotSerialized)
-                {
-                    CreateWordField (Arg0, 0x01, TMP)
-                    FindSetRightBit (TMP, Local0)
-                    Decrement (Local0)
-                    Store (Local0, PRQ3)
-                }
-        }
-    }
-
-    /* S5 = power off state */
-    Name (_S5, Package (4) {
-        0x00, // PM1a_CNT.SLP_TYP 
-        0x00, // PM2a_CNT.SLP_TYP 
-        0x00, // reserved
-        0x00, // reserved
-    })
-}
diff --git a/tools/ioemu/hw/acpi-dsdt.hex b/tools/ioemu/hw/acpi-dsdt.hex
deleted file mode 100644 (file)
index f4f50bd..0000000
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * 
- * Intel ACPI Component Architecture
- * ASL Optimizing Compiler version 20060421 [Apr 29 2006]
- * Copyright (C) 2000 - 2006 Intel Corporation
- * Supports ACPI Specification Revision 3.0a
- * 
- * Compilation of "/usr/local/home/bellard/qemu-current/hw/acpi-dsdt.dsl" - Wed Jun 14 20:09:53 2006
- * 
- * C source code output
- *
- */
-unsigned char AmlCode[] =
-{
-    0x44,0x53,0x44,0x54,0x32,0x08,0x00,0x00,  /* 00000000    "DSDT2..." */
-    0x01,0x5B,0x51,0x45,0x4D,0x55,0x00,0x00,  /* 00000008    ".[QEMU.." */
-    0x51,0x45,0x4D,0x55,0x44,0x53,0x44,0x54,  /* 00000010    "QEMUDSDT" */
-    0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C,  /* 00000018    "....INTL" */
-    0x21,0x04,0x06,0x20,0x10,0x4F,0x04,0x5C,  /* 00000020    "!.. .O.\" */
-    0x00,0x5B,0x80,0x43,0x4D,0x53,0x5F,0x01,  /* 00000028    ".[.CMS_." */
-    0x0A,0x70,0x0A,0x02,0x5B,0x81,0x10,0x43,  /* 00000030    ".p..[..C" */
-    0x4D,0x53,0x5F,0x01,0x43,0x4D,0x53,0x49,  /* 00000038    "MS_.CMSI" */
-    0x08,0x43,0x4D,0x53,0x44,0x08,0x14,0x14,  /* 00000040    ".CMSD..." */
-    0x43,0x4D,0x52,0x44,0x01,0x70,0x68,0x43,  /* 00000048    "CMRD.phC" */
-    0x4D,0x53,0x49,0x70,0x43,0x4D,0x53,0x44,  /* 00000050    "MSIpCMSD" */
-    0x60,0xA4,0x60,0x5B,0x80,0x44,0x42,0x47,  /* 00000058    "`.`[.DBG" */
-    0x5F,0x01,0x0B,0x44,0xB0,0x0A,0x04,0x5B,  /* 00000060    "_..D...[" */
-    0x81,0x0B,0x44,0x42,0x47,0x5F,0x03,0x44,  /* 00000068    "..DBG_.D" */
-    0x42,0x47,0x4C,0x20,0x10,0x4E,0x25,0x5F,  /* 00000070    "BGL .N%_" */
-    0x53,0x42,0x5F,0x5B,0x82,0x46,0x25,0x50,  /* 00000078    "SB_[.F%P" */
-    0x43,0x49,0x30,0x08,0x5F,0x48,0x49,0x44,  /* 00000080    "CI0._HID" */
-    0x0C,0x41,0xD0,0x0A,0x03,0x08,0x5F,0x41,  /* 00000088    ".A...._A" */
-    0x44,0x52,0x00,0x08,0x5F,0x55,0x49,0x44,  /* 00000090    "DR.._UID" */
-    0x01,0x08,0x5F,0x50,0x52,0x54,0x12,0x47,  /* 00000098    ".._PRT.G" */
-    0x15,0x18,0x12,0x0B,0x04,0x0B,0xFF,0xFF,  /* 000000A0    "........" */
-    0x00,0x4C,0x4E,0x4B,0x44,0x00,0x12,0x0B,  /* 000000A8    ".LNKD..." */
-    0x04,0x0B,0xFF,0xFF,0x01,0x4C,0x4E,0x4B,  /* 000000B0    ".....LNK" */
-    0x41,0x00,0x12,0x0C,0x04,0x0B,0xFF,0xFF,  /* 000000B8    "A......." */
-    0x0A,0x02,0x4C,0x4E,0x4B,0x42,0x00,0x12,  /* 000000C0    "..LNKB.." */
-    0x0C,0x04,0x0B,0xFF,0xFF,0x0A,0x03,0x4C,  /* 000000C8    ".......L" */
-    0x4E,0x4B,0x43,0x00,0x12,0x0D,0x04,0x0C,  /* 000000D0    "NKC....." */
-    0xFF,0xFF,0x01,0x00,0x00,0x4C,0x4E,0x4B,  /* 000000D8    ".....LNK" */
-    0x41,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF,  /* 000000E0    "A......." */
-    0x01,0x00,0x01,0x4C,0x4E,0x4B,0x42,0x00,  /* 000000E8    "...LNKB." */
-    0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x01,0x00,  /* 000000F0    "........" */
-    0x0A,0x02,0x4C,0x4E,0x4B,0x43,0x00,0x12,  /* 000000F8    "..LNKC.." */
-    0x0E,0x04,0x0C,0xFF,0xFF,0x01,0x00,0x0A,  /* 00000100    "........" */
-    0x03,0x4C,0x4E,0x4B,0x44,0x00,0x12,0x0D,  /* 00000108    ".LNKD..." */
-    0x04,0x0C,0xFF,0xFF,0x02,0x00,0x00,0x4C,  /* 00000110    ".......L" */
-    0x4E,0x4B,0x42,0x00,0x12,0x0D,0x04,0x0C,  /* 00000118    "NKB....." */
-    0xFF,0xFF,0x02,0x00,0x01,0x4C,0x4E,0x4B,  /* 00000120    ".....LNK" */
-    0x43,0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,  /* 00000128    "C......." */
-    0x02,0x00,0x0A,0x02,0x4C,0x4E,0x4B,0x44,  /* 00000130    "....LNKD" */
-    0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x02,  /* 00000138    "........" */
-    0x00,0x0A,0x03,0x4C,0x4E,0x4B,0x41,0x00,  /* 00000140    "...LNKA." */
-    0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x03,0x00,  /* 00000148    "........" */
-    0x00,0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0D,  /* 00000150    ".LNKC..." */
-    0x04,0x0C,0xFF,0xFF,0x03,0x00,0x01,0x4C,  /* 00000158    ".......L" */
-    0x4E,0x4B,0x44,0x00,0x12,0x0E,0x04,0x0C,  /* 00000160    "NKD....." */
-    0xFF,0xFF,0x03,0x00,0x0A,0x02,0x4C,0x4E,  /* 00000168    "......LN" */
-    0x4B,0x41,0x00,0x12,0x0E,0x04,0x0C,0xFF,  /* 00000170    "KA......" */
-    0xFF,0x03,0x00,0x0A,0x03,0x4C,0x4E,0x4B,  /* 00000178    ".....LNK" */
-    0x42,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF,  /* 00000180    "B......." */
-    0x04,0x00,0x00,0x4C,0x4E,0x4B,0x44,0x00,  /* 00000188    "...LNKD." */
-    0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x04,0x00,  /* 00000190    "........" */
-    0x01,0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0E,  /* 00000198    ".LNKA..." */
-    0x04,0x0C,0xFF,0xFF,0x04,0x00,0x0A,0x02,  /* 000001A0    "........" */
-    0x4C,0x4E,0x4B,0x42,0x00,0x12,0x0E,0x04,  /* 000001A8    "LNKB...." */
-    0x0C,0xFF,0xFF,0x04,0x00,0x0A,0x03,0x4C,  /* 000001B0    ".......L" */
-    0x4E,0x4B,0x43,0x00,0x12,0x0D,0x04,0x0C,  /* 000001B8    "NKC....." */
-    0xFF,0xFF,0x05,0x00,0x00,0x4C,0x4E,0x4B,  /* 000001C0    ".....LNK" */
-    0x41,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF,  /* 000001C8    "A......." */
-    0x05,0x00,0x01,0x4C,0x4E,0x4B,0x42,0x00,  /* 000001D0    "...LNKB." */
-    0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x05,0x00,  /* 000001D8    "........" */
-    0x0A,0x02,0x4C,0x4E,0x4B,0x43,0x00,0x12,  /* 000001E0    "..LNKC.." */
-    0x0E,0x04,0x0C,0xFF,0xFF,0x05,0x00,0x0A,  /* 000001E8    "........" */
-    0x03,0x4C,0x4E,0x4B,0x44,0x00,0x14,0x4C,  /* 000001F0    ".LNKD..L" */
-    0x0D,0x5F,0x43,0x52,0x53,0x00,0x08,0x4D,  /* 000001F8    "._CRS..M" */
-    0x45,0x4D,0x50,0x11,0x42,0x07,0x0A,0x6E,  /* 00000200    "EMP.B..n" */
-    0x88,0x0D,0x00,0x02,0x0C,0x00,0x00,0x00,  /* 00000208    "........" */
-    0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x01,  /* 00000210    "........" */
-    0x47,0x01,0xF8,0x0C,0xF8,0x0C,0x01,0x08,  /* 00000218    "G......." */
-    0x88,0x0D,0x00,0x01,0x0C,0x03,0x00,0x00,  /* 00000220    "........" */
-    0x00,0x00,0xF7,0x0C,0x00,0x00,0xF8,0x0C,  /* 00000228    "........" */
-    0x88,0x0D,0x00,0x01,0x0C,0x03,0x00,0x00,  /* 00000230    "........" */
-    0x00,0x0D,0xFF,0xFF,0x00,0x00,0x00,0xF3,  /* 00000238    "........" */
-    0x87,0x17,0x00,0x00,0x0C,0x03,0x00,0x00,  /* 00000240    "........" */
-    0x00,0x00,0x00,0x00,0x0A,0x00,0xFF,0xFF,  /* 00000248    "........" */
-    0x0B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  /* 00000250    "........" */
-    0x02,0x00,0x87,0x17,0x00,0x00,0x08,0x01,  /* 00000258    "........" */
-    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  /* 00000260    "........" */
-    0xFF,0xFF,0xBF,0xFE,0x00,0x00,0x00,0x00,  /* 00000268    "........" */
-    0x00,0x00,0x00,0x00,0x79,0x00,0x8A,0x4D,  /* 00000270    "....y..M" */
-    0x45,0x4D,0x50,0x0A,0x5C,0x50,0x4D,0x49,  /* 00000278    "EMP.\PMI" */
-    0x4E,0x8A,0x4D,0x45,0x4D,0x50,0x0A,0x60,  /* 00000280    "N.MEMP.`" */
-    0x50,0x4D,0x41,0x58,0x8A,0x4D,0x45,0x4D,  /* 00000288    "PMAX.MEM" */
-    0x50,0x0A,0x68,0x50,0x4C,0x45,0x4E,0x72,  /* 00000290    "P.hPLENr" */
-    0x43,0x4D,0x52,0x44,0x0A,0x34,0x79,0x43,  /* 00000298    "CMRD.4yC" */
-    0x4D,0x52,0x44,0x0A,0x35,0x0A,0x08,0x00,  /* 000002A0    "MRD.5..." */
-    0x60,0x79,0x60,0x0A,0x10,0x60,0x72,0x60,  /* 000002A8    "`y`..`r`" */
-    0x0C,0x00,0x00,0x00,0x01,0x60,0x70,0x60,  /* 000002B0    ".....`p`" */
-    0x50,0x4D,0x49,0x4E,0x74,0x50,0x4D,0x41,  /* 000002B8    "PMINtPMA" */
-    0x58,0x50,0x4D,0x49,0x4E,0x50,0x4C,0x45,  /* 000002C0    "XPMINPLE" */
-    0x4E,0x75,0x50,0x4C,0x45,0x4E,0xA4,0x4D,  /* 000002C8    "NuPLEN.M" */
-    0x45,0x4D,0x50,0x10,0x42,0x26,0x2E,0x5F,  /* 000002D0    "EMP.B&._" */
-    0x53,0x42,0x5F,0x50,0x43,0x49,0x30,0x5B,  /* 000002D8    "SB_PCI0[" */
-    0x82,0x43,0x20,0x49,0x53,0x41,0x5F,0x08,  /* 000002E0    ".C ISA_." */
-    0x5F,0x41,0x44,0x52,0x0C,0x00,0x00,0x01,  /* 000002E8    "_ADR...." */
-    0x00,0x5B,0x80,0x50,0x34,0x30,0x43,0x02,  /* 000002F0    ".[.P40C." */
-    0x0A,0x60,0x0A,0x04,0x5B,0x82,0x44,0x04,  /* 000002F8    ".`..[.D." */
-    0x4B,0x42,0x44,0x5F,0x08,0x5F,0x48,0x49,  /* 00000300    "KBD_._HI" */
-    0x44,0x0C,0x41,0xD0,0x03,0x03,0x14,0x09,  /* 00000308    "D.A....." */
-    0x5F,0x53,0x54,0x41,0x00,0xA4,0x0A,0x0F,  /* 00000310    "_STA...." */
-    0x14,0x29,0x5F,0x43,0x52,0x53,0x00,0x08,  /* 00000318    ".)_CRS.." */
-    0x54,0x4D,0x50,0x5F,0x11,0x18,0x0A,0x15,  /* 00000320    "TMP_...." */
-    0x47,0x01,0x60,0x00,0x60,0x00,0x01,0x01,  /* 00000328    "G.`.`..." */
-    0x47,0x01,0x64,0x00,0x64,0x00,0x01,0x01,  /* 00000330    "G.d.d..." */
-    0x22,0x02,0x00,0x79,0x00,0xA4,0x54,0x4D,  /* 00000338    ""..y..TM" */
-    0x50,0x5F,0x5B,0x82,0x33,0x4D,0x4F,0x55,  /* 00000340    "P_[.3MOU" */
-    0x5F,0x08,0x5F,0x48,0x49,0x44,0x0C,0x41,  /* 00000348    "_._HID.A" */
-    0xD0,0x0F,0x13,0x14,0x09,0x5F,0x53,0x54,  /* 00000350    "....._ST" */
-    0x41,0x00,0xA4,0x0A,0x0F,0x14,0x19,0x5F,  /* 00000358    "A......_" */
-    0x43,0x52,0x53,0x00,0x08,0x54,0x4D,0x50,  /* 00000360    "CRS..TMP" */
-    0x5F,0x11,0x08,0x0A,0x05,0x22,0x00,0x10,  /* 00000368    "_....".." */
-    0x79,0x00,0xA4,0x54,0x4D,0x50,0x5F,0x5B,  /* 00000370    "y..TMP_[" */
-    0x82,0x47,0x04,0x46,0x44,0x43,0x30,0x08,  /* 00000378    ".G.FDC0." */
-    0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0,0x07,  /* 00000380    "_HID.A.." */
-    0x00,0x14,0x09,0x5F,0x53,0x54,0x41,0x00,  /* 00000388    "..._STA." */
-    0xA4,0x0A,0x0F,0x14,0x2C,0x5F,0x43,0x52,  /* 00000390    "....,_CR" */
-    0x53,0x00,0x08,0x42,0x55,0x46,0x30,0x11,  /* 00000398    "S..BUF0." */
-    0x1B,0x0A,0x18,0x47,0x01,0xF2,0x03,0xF2,  /* 000003A0    "...G...." */
-    0x03,0x00,0x04,0x47,0x01,0xF7,0x03,0xF7,  /* 000003A8    "...G...." */
-    0x03,0x00,0x01,0x22,0x40,0x00,0x2A,0x04,  /* 000003B0    "..."@.*." */
-    0x00,0x79,0x00,0xA4,0x42,0x55,0x46,0x30,  /* 000003B8    ".y..BUF0" */
-    0x5B,0x82,0x4B,0x05,0x4C,0x50,0x54,0x5F,  /* 000003C0    "[.K.LPT_" */
-    0x08,0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0,  /* 000003C8    "._HID.A." */
-    0x04,0x00,0x14,0x28,0x5F,0x53,0x54,0x41,  /* 000003D0    "...(_STA" */
-    0x00,0x70,0x5E,0x5E,0x5E,0x2E,0x50,0x58,  /* 000003D8    ".p^^^.PX" */
-    0x31,0x33,0x44,0x52,0x53,0x41,0x60,0x7B,  /* 000003E0    "13DRSA`{" */
-    0x60,0x0C,0x00,0x00,0x00,0x80,0x60,0xA0,  /* 000003E8    "`.....`." */
-    0x06,0x93,0x60,0x00,0xA4,0x00,0xA1,0x04,  /* 000003F0    "..`....." */
-    0xA4,0x0A,0x0F,0x14,0x21,0x5F,0x43,0x52,  /* 000003F8    "....!_CR" */
-    0x53,0x00,0x08,0x42,0x55,0x46,0x30,0x11,  /* 00000400    "S..BUF0." */
-    0x10,0x0A,0x0D,0x47,0x01,0x78,0x03,0x78,  /* 00000408    "...G.x.x" */
-    0x03,0x08,0x08,0x22,0x80,0x00,0x79,0x00,  /* 00000410    "..."..y." */
-    0xA4,0x42,0x55,0x46,0x30,0x5B,0x82,0x41,  /* 00000418    ".BUF0[.A" */
-    0x06,0x43,0x4F,0x4D,0x31,0x08,0x5F,0x48,  /* 00000420    ".COM1._H" */
-    0x49,0x44,0x0C,0x41,0xD0,0x05,0x01,0x08,  /* 00000428    "ID.A...." */
-    0x5F,0x55,0x49,0x44,0x01,0x14,0x28,0x5F,  /* 00000430    "_UID..(_" */
-    0x53,0x54,0x41,0x00,0x70,0x5E,0x5E,0x5E,  /* 00000438    "STA.p^^^" */
-    0x2E,0x50,0x58,0x31,0x33,0x44,0x52,0x53,  /* 00000440    ".PX13DRS" */
-    0x43,0x60,0x7B,0x60,0x0C,0x00,0x00,0x00,  /* 00000448    "C`{`...." */
-    0x08,0x60,0xA0,0x06,0x93,0x60,0x00,0xA4,  /* 00000450    ".`...`.." */
-    0x00,0xA1,0x04,0xA4,0x0A,0x0F,0x14,0x21,  /* 00000458    ".......!" */
-    0x5F,0x43,0x52,0x53,0x00,0x08,0x42,0x55,  /* 00000460    "_CRS..BU" */
-    0x46,0x30,0x11,0x10,0x0A,0x0D,0x47,0x01,  /* 00000468    "F0....G." */
-    0xF8,0x03,0xF8,0x03,0x00,0x08,0x22,0x10,  /* 00000470    "......"." */
-    0x00,0x79,0x00,0xA4,0x42,0x55,0x46,0x30,  /* 00000478    ".y..BUF0" */
-    0x5B,0x82,0x42,0x06,0x43,0x4F,0x4D,0x32,  /* 00000480    "[.B.COM2" */
-    0x08,0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0,  /* 00000488    "._HID.A." */
-    0x05,0x01,0x08,0x5F,0x55,0x49,0x44,0x0A,  /* 00000490    "..._UID." */
-    0x02,0x14,0x28,0x5F,0x53,0x54,0x41,0x00,  /* 00000498    "..(_STA." */
-    0x70,0x5E,0x5E,0x5E,0x2E,0x50,0x58,0x31,  /* 000004A0    "p^^^.PX1" */
-    0x33,0x44,0x52,0x53,0x43,0x60,0x7B,0x60,  /* 000004A8    "3DRSC`{`" */
-    0x0C,0x00,0x00,0x00,0x80,0x60,0xA0,0x06,  /* 000004B0    ".....`.." */
-    0x93,0x60,0x00,0xA4,0x00,0xA1,0x04,0xA4,  /* 000004B8    ".`......" */
-    0x0A,0x0F,0x14,0x21,0x5F,0x43,0x52,0x53,  /* 000004C0    "...!_CRS" */
-    0x00,0x08,0x42,0x55,0x46,0x30,0x11,0x10,  /* 000004C8    "..BUF0.." */
-    0x0A,0x0D,0x47,0x01,0xF8,0x02,0xF8,0x02,  /* 000004D0    "..G....." */
-    0x00,0x08,0x22,0x08,0x00,0x79,0x00,0xA4,  /* 000004D8    ".."..y.." */
-    0x42,0x55,0x46,0x30,0x5B,0x82,0x40,0x05,  /* 000004E0    "BUF0[.@." */
-    0x50,0x58,0x31,0x33,0x08,0x5F,0x41,0x44,  /* 000004E8    "PX13._AD" */
-    0x52,0x0C,0x03,0x00,0x01,0x00,0x5B,0x80,  /* 000004F0    "R.....[." */
-    0x50,0x31,0x33,0x43,0x02,0x0A,0x5C,0x0A,  /* 000004F8    "P13C..\." */
-    0x24,0x5B,0x81,0x33,0x50,0x31,0x33,0x43,  /* 00000500    "$[.3P13C" */
-    0x03,0x44,0x52,0x53,0x41,0x20,0x44,0x52,  /* 00000508    ".DRSA DR" */
-    0x53,0x42,0x20,0x44,0x52,0x53,0x43,0x20,  /* 00000510    "SB DRSC " */
-    0x44,0x52,0x53,0x45,0x20,0x44,0x52,0x53,  /* 00000518    "DRSE DRS" */
-    0x46,0x20,0x44,0x52,0x53,0x47,0x20,0x44,  /* 00000520    "F DRSG D" */
-    0x52,0x53,0x48,0x20,0x44,0x52,0x53,0x49,  /* 00000528    "RSH DRSI" */
-    0x20,0x44,0x52,0x53,0x4A,0x20,0x10,0x4F,  /* 00000530    " DRSJ .O" */
-    0x2E,0x5F,0x53,0x42,0x5F,0x5B,0x81,0x24,  /* 00000538    "._SB_[.$" */
-    0x2F,0x03,0x50,0x43,0x49,0x30,0x49,0x53,  /* 00000540    "/.PCI0IS" */
-    0x41,0x5F,0x50,0x34,0x30,0x43,0x01,0x50,  /* 00000548    "A_P40C.P" */
-    0x52,0x51,0x30,0x08,0x50,0x52,0x51,0x31,  /* 00000550    "RQ0.PRQ1" */
-    0x08,0x50,0x52,0x51,0x32,0x08,0x50,0x52,  /* 00000558    ".PRQ2.PR" */
-    0x51,0x33,0x08,0x5B,0x82,0x4E,0x0A,0x4C,  /* 00000560    "Q3.[.N.L" */
-    0x4E,0x4B,0x41,0x08,0x5F,0x48,0x49,0x44,  /* 00000568    "NKA._HID" */
-    0x0C,0x41,0xD0,0x0C,0x0F,0x08,0x5F,0x55,  /* 00000570    ".A...._U" */
-    0x49,0x44,0x01,0x08,0x5F,0x50,0x52,0x53,  /* 00000578    "ID.._PRS" */
-    0x11,0x09,0x0A,0x06,0x23,0xF8,0x1E,0x18,  /* 00000580    "....#..." */
-    0x79,0x00,0x14,0x1A,0x5F,0x53,0x54,0x41,  /* 00000588    "y..._STA" */
-    0x00,0x70,0x0A,0x0B,0x60,0xA0,0x0D,0x7B,  /* 00000590    ".p..`..{" */
-    0x0A,0x80,0x50,0x52,0x51,0x30,0x61,0x70,  /* 00000598    "..PRQ0ap" */
-    0x0A,0x09,0x60,0xA4,0x60,0x14,0x11,0x5F,  /* 000005A0    "..`.`.._" */
-    0x44,0x49,0x53,0x00,0x7D,0x50,0x52,0x51,  /* 000005A8    "DIS.}PRQ" */
-    0x30,0x0A,0x80,0x50,0x52,0x51,0x30,0x14,  /* 000005B0    "0..PRQ0." */
-    0x3F,0x5F,0x43,0x52,0x53,0x00,0x08,0x50,  /* 000005B8    "?_CRS..P" */
-    0x52,0x52,0x30,0x11,0x09,0x0A,0x06,0x23,  /* 000005C0    "RR0....#" */
-    0x02,0x00,0x18,0x79,0x00,0x8B,0x50,0x52,  /* 000005C8    "...y..PR" */
-    0x52,0x30,0x01,0x54,0x4D,0x50,0x5F,0x70,  /* 000005D0    "R0.TMP_p" */
-    0x50,0x52,0x51,0x30,0x60,0xA0,0x0C,0x95,  /* 000005D8    "PRQ0`..." */
-    0x60,0x0A,0x80,0x79,0x01,0x60,0x54,0x4D,  /* 000005E0    "`..y.`TM" */
-    0x50,0x5F,0xA1,0x07,0x70,0x00,0x54,0x4D,  /* 000005E8    "P_..p.TM" */
-    0x50,0x5F,0xA4,0x50,0x52,0x52,0x30,0x14,  /* 000005F0    "P_.PRR0." */
-    0x1B,0x5F,0x53,0x52,0x53,0x01,0x8B,0x68,  /* 000005F8    "._SRS..h" */
-    0x01,0x54,0x4D,0x50,0x5F,0x82,0x54,0x4D,  /* 00000600    ".TMP_.TM" */
-    0x50,0x5F,0x60,0x76,0x60,0x70,0x60,0x50,  /* 00000608    "P_`v`p`P" */
-    0x52,0x51,0x30,0x5B,0x82,0x4F,0x0A,0x4C,  /* 00000610    "RQ0[.O.L" */
-    0x4E,0x4B,0x42,0x08,0x5F,0x48,0x49,0x44,  /* 00000618    "NKB._HID" */
-    0x0C,0x41,0xD0,0x0C,0x0F,0x08,0x5F,0x55,  /* 00000620    ".A...._U" */
-    0x49,0x44,0x0A,0x02,0x08,0x5F,0x50,0x52,  /* 00000628    "ID..._PR" */
-    0x53,0x11,0x09,0x0A,0x06,0x23,0xF8,0x1E,  /* 00000630    "S....#.." */
-    0x18,0x79,0x00,0x14,0x1A,0x5F,0x53,0x54,  /* 00000638    ".y..._ST" */
-    0x41,0x00,0x70,0x0A,0x0B,0x60,0xA0,0x0D,  /* 00000640    "A.p..`.." */
-    0x7B,0x0A,0x80,0x50,0x52,0x51,0x31,0x61,  /* 00000648    "{..PRQ1a" */
-    0x70,0x0A,0x09,0x60,0xA4,0x60,0x14,0x11,  /* 00000650    "p..`.`.." */
-    0x5F,0x44,0x49,0x53,0x00,0x7D,0x50,0x52,  /* 00000658    "_DIS.}PR" */
-    0x51,0x31,0x0A,0x80,0x50,0x52,0x51,0x31,  /* 00000660    "Q1..PRQ1" */
-    0x14,0x3F,0x5F,0x43,0x52,0x53,0x00,0x08,  /* 00000668    ".?_CRS.." */
-    0x50,0x52,0x52,0x30,0x11,0x09,0x0A,0x06,  /* 00000670    "PRR0...." */
-    0x23,0x02,0x00,0x18,0x79,0x00,0x8B,0x50,  /* 00000678    "#...y..P" */
-    0x52,0x52,0x30,0x01,0x54,0x4D,0x50,0x5F,  /* 00000680    "RR0.TMP_" */
-    0x70,0x50,0x52,0x51,0x31,0x60,0xA0,0x0C,  /* 00000688    "pPRQ1`.." */
-    0x95,0x60,0x0A,0x80,0x79,0x01,0x60,0x54,  /* 00000690    ".`..y.`T" */
-    0x4D,0x50,0x5F,0xA1,0x07,0x70,0x00,0x54,  /* 00000698    "MP_..p.T" */
-    0x4D,0x50,0x5F,0xA4,0x50,0x52,0x52,0x30,  /* 000006A0    "MP_.PRR0" */
-    0x14,0x1B,0x5F,0x53,0x52,0x53,0x01,0x8B,  /* 000006A8    ".._SRS.." */
-    0x68,0x01,0x54,0x4D,0x50,0x5F,0x82,0x54,  /* 000006B0    "h.TMP_.T" */
-    0x4D,0x50,0x5F,0x60,0x76,0x60,0x70,0x60,  /* 000006B8    "MP_`v`p`" */
-    0x50,0x52,0x51,0x31,0x5B,0x82,0x4F,0x0A,  /* 000006C0    "PRQ1[.O." */
-    0x4C,0x4E,0x4B,0x43,0x08,0x5F,0x48,0x49,  /* 000006C8    "LNKC._HI" */
-    0x44,0x0C,0x41,0xD0,0x0C,0x0F,0x08,0x5F,  /* 000006D0    "D.A...._" */
-    0x55,0x49,0x44,0x0A,0x03,0x08,0x5F,0x50,  /* 000006D8    "UID..._P" */
-    0x52,0x53,0x11,0x09,0x0A,0x06,0x23,0xF8,  /* 000006E0    "RS....#." */
-    0x1E,0x18,0x79,0x00,0x14,0x1A,0x5F,0x53,  /* 000006E8    "..y..._S" */
-    0x54,0x41,0x00,0x70,0x0A,0x0B,0x60,0xA0,  /* 000006F0    "TA.p..`." */
-    0x0D,0x7B,0x0A,0x80,0x50,0x52,0x51,0x32,  /* 000006F8    ".{..PRQ2" */
-    0x61,0x70,0x0A,0x09,0x60,0xA4,0x60,0x14,  /* 00000700    "ap..`.`." */
-    0x11,0x5F,0x44,0x49,0x53,0x00,0x7D,0x50,  /* 00000708    "._DIS.}P" */
-    0x52,0x51,0x32,0x0A,0x80,0x50,0x52,0x51,  /* 00000710    "RQ2..PRQ" */
-    0x32,0x14,0x3F,0x5F,0x43,0x52,0x53,0x00,  /* 00000718    "2.?_CRS." */
-    0x08,0x50,0x52,0x52,0x30,0x11,0x09,0x0A,  /* 00000720    ".PRR0..." */
-    0x06,0x23,0x02,0x00,0x18,0x79,0x00,0x8B,  /* 00000728    ".#...y.." */
-    0x50,0x52,0x52,0x30,0x01,0x54,0x4D,0x50,  /* 00000730    "PRR0.TMP" */
-    0x5F,0x70,0x50,0x52,0x51,0x32,0x60,0xA0,  /* 00000738    "_pPRQ2`." */
-    0x0C,0x95,0x60,0x0A,0x80,0x79,0x01,0x60,  /* 00000740    "..`..y.`" */
-    0x54,0x4D,0x50,0x5F,0xA1,0x07,0x70,0x00,  /* 00000748    "TMP_..p." */
-    0x54,0x4D,0x50,0x5F,0xA4,0x50,0x52,0x52,  /* 00000750    "TMP_.PRR" */
-    0x30,0x14,0x1B,0x5F,0x53,0x52,0x53,0x01,  /* 00000758    "0.._SRS." */
-    0x8B,0x68,0x01,0x54,0x4D,0x50,0x5F,0x82,  /* 00000760    ".h.TMP_." */
-    0x54,0x4D,0x50,0x5F,0x60,0x76,0x60,0x70,  /* 00000768    "TMP_`v`p" */
-    0x60,0x50,0x52,0x51,0x32,0x5B,0x82,0x4F,  /* 00000770    "`PRQ2[.O" */
-    0x0A,0x4C,0x4E,0x4B,0x44,0x08,0x5F,0x48,  /* 00000778    ".LNKD._H" */
-    0x49,0x44,0x0C,0x41,0xD0,0x0C,0x0F,0x08,  /* 00000780    "ID.A...." */
-    0x5F,0x55,0x49,0x44,0x0A,0x04,0x08,0x5F,  /* 00000788    "_UID..._" */
-    0x50,0x52,0x53,0x11,0x09,0x0A,0x06,0x23,  /* 00000790    "PRS....#" */
-    0xF8,0x1E,0x18,0x79,0x00,0x14,0x1A,0x5F,  /* 00000798    "...y..._" */
-    0x53,0x54,0x41,0x00,0x70,0x0A,0x0B,0x60,  /* 000007A0    "STA.p..`" */
-    0xA0,0x0D,0x7B,0x0A,0x80,0x50,0x52,0x51,  /* 000007A8    "..{..PRQ" */
-    0x33,0x61,0x70,0x0A,0x09,0x60,0xA4,0x60,  /* 000007B0    "3ap..`.`" */
-    0x14,0x11,0x5F,0x44,0x49,0x53,0x00,0x7D,  /* 000007B8    ".._DIS.}" */
-    0x50,0x52,0x51,0x33,0x0A,0x80,0x50,0x52,  /* 000007C0    "PRQ3..PR" */
-    0x51,0x33,0x14,0x3F,0x5F,0x43,0x52,0x53,  /* 000007C8    "Q3.?_CRS" */
-    0x00,0x08,0x50,0x52,0x52,0x30,0x11,0x09,  /* 000007D0    "..PRR0.." */
-    0x0A,0x06,0x23,0x02,0x00,0x18,0x79,0x00,  /* 000007D8    "..#...y." */
-    0x8B,0x50,0x52,0x52,0x30,0x01,0x54,0x4D,  /* 000007E0    ".PRR0.TM" */
-    0x50,0x5F,0x70,0x50,0x52,0x51,0x33,0x60,  /* 000007E8    "P_pPRQ3`" */
-    0xA0,0x0C,0x95,0x60,0x0A,0x80,0x79,0x01,  /* 000007F0    "...`..y." */
-    0x60,0x54,0x4D,0x50,0x5F,0xA1,0x07,0x70,  /* 000007F8    "`TMP_..p" */
-    0x00,0x54,0x4D,0x50,0x5F,0xA4,0x50,0x52,  /* 00000800    ".TMP_.PR" */
-    0x52,0x30,0x14,0x1B,0x5F,0x53,0x52,0x53,  /* 00000808    "R0.._SRS" */
-    0x01,0x8B,0x68,0x01,0x54,0x4D,0x50,0x5F,  /* 00000810    "..h.TMP_" */
-    0x82,0x54,0x4D,0x50,0x5F,0x60,0x76,0x60,  /* 00000818    ".TMP_`v`" */
-    0x70,0x60,0x50,0x52,0x51,0x33,0x08,0x5F,  /* 00000820    "p`PRQ3._" */
-    0x53,0x35,0x5F,0x12,0x06,0x04,0x00,0x00,  /* 00000828    "S5_....." */
-    0x00,0x00,
-};
index 6c20a4e937b6e940c1bd7f4a8f3fabf5a8fb452b..78c4feabbf7fcf6472d3463fff590a3afe3d54f2 100644 (file)
 /* i82731AB (PIIX4) compatible power management function */
 #define PM_FREQ 3579545
 
-/* XXX: make them variable */
-#define PM_IO_BASE        0xb000
-#define SMI_CMD_IO_ADDR   0xb040
 #define ACPI_DBG_IO_ADDR  0xb044
+#define SMB_IO_BASE       0xb100
 
 typedef struct PIIX4PMState {
     PCIDevice dev;
     uint16_t pmsts;
     uint16_t pmen;
     uint16_t pmcntrl;
+    uint8_t apmc;
+    uint8_t apms;
     QEMUTimer *tmr_timer;
     int64_t tmr_overflow_time;
+    SMBusDevice *smb_dev[128];
+    uint8_t smb_stat;
+    uint8_t smb_ctl;
+    uint8_t smb_cmd;
+    uint8_t smb_addr;
+    uint8_t smb_data0;
+    uint8_t smb_data1;
+    uint8_t smb_data[32];
+    uint8_t smb_index;
 } PIIX4PMState;
 
 #define RTC_EN (1 << 10)
@@ -46,8 +55,15 @@ typedef struct PIIX4PMState {
 
 #define SUS_EN (1 << 13)
 
-/* Note: only used for ACPI bios init. Could be deleted when ACPI init
-   is integrated in Bochs BIOS */
+#define SMBHSTSTS 0x00
+#define SMBHSTCNT 0x02
+#define SMBHSTCMD 0x03
+#define SMBHSTADD 0x04
+#define SMBHSTDAT0 0x05
+#define SMBHSTDAT1 0x06
+#define SMBBLKDAT 0x07
+
+/* Note: only used for piix4_smbus_register_device */
 static PIIX4PMState *piix4_pm_state;
 
 static uint32_t get_pmtmr(PIIX4PMState *s)
@@ -195,20 +211,38 @@ static uint32_t pm_ioport_readl(void *opaque, uint32_t addr)
     return val;
 }
 
-static void smi_cmd_writeb(void *opaque, uint32_t addr, uint32_t val)
+static void pm_smi_writeb(void *opaque, uint32_t addr, uint32_t val)
 {
     PIIX4PMState *s = opaque;
+    addr &= 1;
 #ifdef DEBUG
-    printf("SMI cmd val=0x%02x\n", val);
+    printf("pm_smi_writeb addr=0x%x val=0x%02x\n", addr, val);
 #endif
-    switch(val) {
-    case 0xf0: /* ACPI disable */
-        s->pmcntrl &= ~SCI_EN;
-        break;
-    case 0xf1: /* ACPI enable */
-        s->pmcntrl |= SCI_EN;
-        break;
+    if (addr == 0) {
+        s->apmc = val;
+        if (s->dev.config[0x5b] & (1 << 1)) {
+            cpu_interrupt(first_cpu, CPU_INTERRUPT_SMI);
+        }
+    } else {
+        s->apms = val;
+    }
+}
+
+static uint32_t pm_smi_readb(void *opaque, uint32_t addr)
+{
+    PIIX4PMState *s = opaque;
+    uint32_t val;
+    
+    addr &= 1;
+    if (addr == 0) {
+        val = s->apmc;
+    } else {
+        val = s->apms;
     }
+#ifdef DEBUG
+    printf("pm_smi_readb addr=0x%x val=0x%02x\n", addr, val);
+#endif
+    return val;
 }
 
 static void acpi_dbg_writel(void *opaque, uint32_t addr, uint32_t val)
@@ -218,398 +252,272 @@ static void acpi_dbg_writel(void *opaque, uint32_t addr, uint32_t val)
 #endif
 }
 
-/* XXX: we still add it to the PIIX3 and we count on the fact that
-   OSes are smart enough to accept this strange configuration */
-void piix4_pm_init(PCIBus *bus, int devfn)
+static void smb_transaction(PIIX4PMState *s)
 {
-    PIIX4PMState *s;
-    uint8_t *pci_conf;
-    uint32_t pm_io_base;
+    uint8_t prot = (s->smb_ctl >> 2) & 0x07;
+    uint8_t read = s->smb_addr & 0x01;
+    uint8_t cmd = s->smb_cmd;
+    uint8_t addr = s->smb_addr >> 1;
+    SMBusDevice *dev = s->smb_dev[addr];
 
-    s = (PIIX4PMState *)pci_register_device(bus,
-                                         "PM", sizeof(PIIX4PMState),
-                                         devfn, NULL, NULL);
-    pci_conf = s->dev.config;
-    pci_conf[0x00] = 0x86;
-    pci_conf[0x01] = 0x80;
-    pci_conf[0x02] = 0x13;
-    pci_conf[0x03] = 0x71;
-    pci_conf[0x08] = 0x00; // revision number
-    pci_conf[0x09] = 0x00;
-    pci_conf[0x0a] = 0x80; // other bridge device
-    pci_conf[0x0b] = 0x06; // bridge device
-    pci_conf[0x0e] = 0x00; // header_type
-    pci_conf[0x3d] = 0x01; // interrupt pin 1
-    
-    pm_io_base = PM_IO_BASE;
-    pci_conf[0x40] = pm_io_base | 1;
-    pci_conf[0x41] = pm_io_base >> 8;
-    register_ioport_write(pm_io_base, 64, 2, pm_ioport_writew, s);
-    register_ioport_read(pm_io_base, 64, 2, pm_ioport_readw, s);
-    register_ioport_write(pm_io_base, 64, 4, pm_ioport_writel, s);
-    register_ioport_read(pm_io_base, 64, 4, pm_ioport_readl, s);
-    
-    register_ioport_write(SMI_CMD_IO_ADDR, 1, 1, smi_cmd_writeb, s);
-    register_ioport_write(ACPI_DBG_IO_ADDR, 4, 4, acpi_dbg_writel, s);
+#ifdef DEBUG
+    printf("SMBus trans addr=0x%02x prot=0x%02x\n", addr, prot);
+#endif
+    if (!dev) goto error;
 
-    /* XXX: which specification is used ? The i82731AB has different
-       mappings */
-    pci_conf[0x5f] = (parallel_hds[0] != NULL ? 0x80 : 0) | 0x10;
-    pci_conf[0x63] = 0x60;
-    pci_conf[0x67] = (serial_hds[0] != NULL ? 0x08 : 0) |
-       (serial_hds[1] != NULL ? 0x90 : 0);
+    switch(prot) {
+    case 0x0:
+        if (!dev->quick_cmd) goto error;
+        (*dev->quick_cmd)(dev, read);
+        break;
+    case 0x1:
+        if (read) {
+            if (!dev->receive_byte) goto error;
+            s->smb_data0 = (*dev->receive_byte)(dev);
+        }
+        else {
+            if (!dev->send_byte) goto error;
+            (*dev->send_byte)(dev, cmd);
+        }
+        break;
+    case 0x2:
+        if (read) {
+            if (!dev->read_byte) goto error;
+            s->smb_data0 = (*dev->read_byte)(dev, cmd);
+        }
+        else {
+            if (!dev->write_byte) goto error;
+            (*dev->write_byte)(dev, cmd, s->smb_data0);
+        }
+        break;
+    case 0x3:
+        if (read) {
+            uint16_t val;
+            if (!dev->read_word) goto error;
+            val = (*dev->read_word)(dev, cmd);
+            s->smb_data0 = val;
+            s->smb_data1 = val >> 8;
+        }
+        else {
+            if (!dev->write_word) goto error;
+            (*dev->write_word)(dev, cmd, (s->smb_data1 << 8) | s->smb_data0);
+        }
+        break;
+    case 0x5:
+        if (read) {
+            if (!dev->read_block) goto error;
+            s->smb_data0 = (*dev->read_block)(dev, cmd, s->smb_data);
+        }
+        else {
+            if (!dev->write_block) goto error;
+            (*dev->write_block)(dev, cmd, s->smb_data0, s->smb_data);
+        }
+        break;
+    default:
+        goto error;
+    }
+    return;
 
-    s->tmr_timer = qemu_new_timer(vm_clock, pm_tmr_timer, s);
-    piix4_pm_state = s;
+  error:
+    s->smb_stat |= 0x04;
 }
 
-/* ACPI tables */
-/* XXX: move them in the Bochs BIOS ? */
-
-/*************************************************/
-
-/* Table structure from Linux kernel (the ACPI tables are under the
-   BSD license) */
-
-#define ACPI_TABLE_HEADER_DEF   /* ACPI common table header */ \
-       uint8_t                            signature [4];          /* ACPI signature (4 ASCII characters) */\
-       uint32_t                             length;                 /* Length of table, in bytes, including header */\
-       uint8_t                              revision;               /* ACPI Specification minor version # */\
-       uint8_t                              checksum;               /* To make sum of entire table == 0 */\
-       uint8_t                            oem_id [6];             /* OEM identification */\
-       uint8_t                            oem_table_id [8];       /* OEM table identification */\
-       uint32_t                             oem_revision;           /* OEM revision number */\
-       uint8_t                            asl_compiler_id [4];    /* ASL compiler vendor ID */\
-       uint32_t                             asl_compiler_revision;  /* ASL compiler revision number */
-
-
-struct acpi_table_header         /* ACPI common table header */
+static void smb_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
 {
-       ACPI_TABLE_HEADER_DEF
-};
+    PIIX4PMState *s = opaque;
+    addr &= 0x3f;
+#ifdef DEBUG
+    printf("SMB writeb port=0x%04x val=0x%02x\n", addr, val);
+#endif
+    switch(addr) {
+    case SMBHSTSTS:
+        s->smb_stat = 0;
+        s->smb_index = 0;
+        break;
+    case SMBHSTCNT:
+        s->smb_ctl = val;
+        if (val & 0x40)
+            smb_transaction(s);
+        break;
+    case SMBHSTCMD:
+        s->smb_cmd = val;
+        break;
+    case SMBHSTADD:
+        s->smb_addr = val;
+        break;
+    case SMBHSTDAT0:
+        s->smb_data0 = val;
+        break;
+    case SMBHSTDAT1:
+        s->smb_data1 = val;
+        break;
+    case SMBBLKDAT:
+        s->smb_data[s->smb_index++] = val;
+        if (s->smb_index > 31)
+            s->smb_index = 0;
+        break;
+    default:
+        break;
+    }
+}
 
-struct rsdp_descriptor         /* Root System Descriptor Pointer */
+static uint32_t smb_ioport_readb(void *opaque, uint32_t addr)
 {
-       uint8_t                            signature [8];          /* ACPI signature, contains "RSD PTR " */
-       uint8_t                              checksum;               /* To make sum of struct == 0 */
-       uint8_t                            oem_id [6];             /* OEM identification */
-       uint8_t                              revision;               /* Must be 0 for 1.0, 2 for 2.0 */
-       uint32_t                             rsdt_physical_address;  /* 32-bit physical address of RSDT */
-       uint32_t                             length;                 /* XSDT Length in bytes including hdr */
-       uint64_t                             xsdt_physical_address;  /* 64-bit physical address of XSDT */
-       uint8_t                              extended_checksum;      /* Checksum of entire table */
-       uint8_t                            reserved [3];           /* Reserved field must be 0 */
-};
+    PIIX4PMState *s = opaque;
+    uint32_t val;
 
-/*
- * ACPI 1.0 Root System Description Table (RSDT)
- */
-struct rsdt_descriptor_rev1
-{
-       ACPI_TABLE_HEADER_DEF                           /* ACPI common table header */
-       uint32_t                             table_offset_entry [2]; /* Array of pointers to other */
-                        /* ACPI tables */
-};
+    addr &= 0x3f;
+    switch(addr) {
+    case SMBHSTSTS:
+        val = s->smb_stat;
+        break;
+    case SMBHSTCNT:
+        s->smb_index = 0;
+        val = s->smb_ctl & 0x1f;
+        break;
+    case SMBHSTCMD:
+        val = s->smb_cmd;
+        break;
+    case SMBHSTADD:
+        val = s->smb_addr;
+        break;
+    case SMBHSTDAT0:
+        val = s->smb_data0;
+        break;
+    case SMBHSTDAT1:
+        val = s->smb_data1;
+        break;
+    case SMBBLKDAT:
+        val = s->smb_data[s->smb_index++];
+        if (s->smb_index > 31)
+            s->smb_index = 0;
+        break;
+    default:
+        val = 0;
+        break;
+    }
+#ifdef DEBUG
+    printf("SMB readb port=0x%04x val=0x%02x\n", addr, val);
+#endif
+    return val;
+}
 
-/*
- * ACPI 1.0 Firmware ACPI Control Structure (FACS)
- */
-struct facs_descriptor_rev1
+static void pm_io_space_update(PIIX4PMState *s)
 {
-       uint8_t                            signature[4];           /* ACPI Signature */
-       uint32_t                             length;                 /* Length of structure, in bytes */
-       uint32_t                             hardware_signature;     /* Hardware configuration signature */
-       uint32_t                             firmware_waking_vector; /* ACPI OS waking vector */
-       uint32_t                             global_lock;            /* Global Lock */
-       uint32_t                             S4bios_f        : 1;    /* Indicates if S4BIOS support is present */
-       uint32_t                             reserved1       : 31;   /* Must be 0 */
-       uint8_t                              resverved3 [40];        /* Reserved - must be zero */
-};
+    uint32_t pm_io_base;
 
+    if (s->dev.config[0x80] & 1) {
+        pm_io_base = le32_to_cpu(*(uint32_t *)(s->dev.config + 0x40));
+        pm_io_base &= 0xfffe;
 
-/*
- * ACPI 1.0 Fixed ACPI Description Table (FADT)
- */
-struct fadt_descriptor_rev1
-{
-       ACPI_TABLE_HEADER_DEF                           /* ACPI common table header */
-       uint32_t                             firmware_ctrl;          /* Physical address of FACS */
-       uint32_t                             dsdt;                   /* Physical address of DSDT */
-       uint8_t                              model;                  /* System Interrupt Model */
-       uint8_t                              reserved1;              /* Reserved */
-       uint16_t                             sci_int;                /* System vector of SCI interrupt */
-       uint32_t                             smi_cmd;                /* Port address of SMI command port */
-       uint8_t                              acpi_enable;            /* Value to write to smi_cmd to enable ACPI */
-       uint8_t                              acpi_disable;           /* Value to write to smi_cmd to disable ACPI */
-       uint8_t                              S4bios_req;             /* Value to write to SMI CMD to enter S4BIOS state */
-       uint8_t                              reserved2;              /* Reserved - must be zero */
-       uint32_t                             pm1a_evt_blk;           /* Port address of Power Mgt 1a acpi_event Reg Blk */
-       uint32_t                             pm1b_evt_blk;           /* Port address of Power Mgt 1b acpi_event Reg Blk */
-       uint32_t                             pm1a_cnt_blk;           /* Port address of Power Mgt 1a Control Reg Blk */
-       uint32_t                             pm1b_cnt_blk;           /* Port address of Power Mgt 1b Control Reg Blk */
-       uint32_t                             pm2_cnt_blk;            /* Port address of Power Mgt 2 Control Reg Blk */
-       uint32_t                             pm_tmr_blk;             /* Port address of Power Mgt Timer Ctrl Reg Blk */
-       uint32_t                             gpe0_blk;               /* Port addr of General Purpose acpi_event 0 Reg Blk */
-       uint32_t                             gpe1_blk;               /* Port addr of General Purpose acpi_event 1 Reg Blk */
-       uint8_t                              pm1_evt_len;            /* Byte length of ports at pm1_x_evt_blk */
-       uint8_t                              pm1_cnt_len;            /* Byte length of ports at pm1_x_cnt_blk */
-       uint8_t                              pm2_cnt_len;            /* Byte Length of ports at pm2_cnt_blk */
-       uint8_t                              pm_tmr_len;              /* Byte Length of ports at pm_tm_blk */
-       uint8_t                              gpe0_blk_len;           /* Byte Length of ports at gpe0_blk */
-       uint8_t                              gpe1_blk_len;           /* Byte Length of ports at gpe1_blk */
-       uint8_t                              gpe1_base;              /* Offset in gpe model where gpe1 events start */
-       uint8_t                              reserved3;              /* Reserved */
-       uint16_t                             plvl2_lat;              /* Worst case HW latency to enter/exit C2 state */
-       uint16_t                             plvl3_lat;              /* Worst case HW latency to enter/exit C3 state */
-       uint16_t                             flush_size;             /* Size of area read to flush caches */
-       uint16_t                             flush_stride;           /* Stride used in flushing caches */
-       uint8_t                              duty_offset;            /* Bit location of duty cycle field in p_cnt reg */
-       uint8_t                              duty_width;             /* Bit width of duty cycle field in p_cnt reg */
-       uint8_t                              day_alrm;               /* Index to day-of-month alarm in RTC CMOS RAM */
-       uint8_t                              mon_alrm;               /* Index to month-of-year alarm in RTC CMOS RAM */
-       uint8_t                              century;                /* Index to century in RTC CMOS RAM */
-       uint8_t                              reserved4;              /* Reserved */
-       uint8_t                              reserved4a;             /* Reserved */
-       uint8_t                              reserved4b;             /* Reserved */
-#if 0
-       uint32_t                             wb_invd         : 1;    /* The wbinvd instruction works properly */
-       uint32_t                             wb_invd_flush   : 1;    /* The wbinvd flushes but does not invalidate */
-       uint32_t                             proc_c1         : 1;    /* All processors support C1 state */
-       uint32_t                             plvl2_up        : 1;    /* C2 state works on MP system */
-       uint32_t                             pwr_button      : 1;    /* Power button is handled as a generic feature */
-       uint32_t                             sleep_button    : 1;    /* Sleep button is handled as a generic feature, or not present */
-       uint32_t                             fixed_rTC       : 1;    /* RTC wakeup stat not in fixed register space */
-       uint32_t                             rtcs4           : 1;    /* RTC wakeup stat not possible from S4 */
-       uint32_t                             tmr_val_ext     : 1;    /* The tmr_val width is 32 bits (0 = 24 bits) */
-       uint32_t                             reserved5       : 23;   /* Reserved - must be zero */
-#else
-        uint32_t flags;
+        /* XXX: need to improve memory and ioport allocation */
+#if defined(DEBUG)
+        printf("PM: mapping to 0x%x\n", pm_io_base);
 #endif
-};
-
-/*
- * MADT values and structures
- */
+        register_ioport_write(pm_io_base, 64, 2, pm_ioport_writew, s);
+        register_ioport_read(pm_io_base, 64, 2, pm_ioport_readw, s);
+        register_ioport_write(pm_io_base, 64, 4, pm_ioport_writel, s);
+        register_ioport_read(pm_io_base, 64, 4, pm_ioport_readl, s);
+    }
+}
 
-/* Values for MADT PCATCompat */
+static void pm_write_config(PCIDevice *d, 
+                            uint32_t address, uint32_t val, int len)
+{
+    pci_default_write_config(d, address, val, len);
+    if (address == 0x80)
+        pm_io_space_update((PIIX4PMState *)d);
+}
 
-#define DUAL_PIC                0
-#define MULTIPLE_APIC           1
+static void pm_save(QEMUFile* f,void *opaque)
+{
+    PIIX4PMState *s = opaque;
 
+    pci_device_save(&s->dev, f);
 
-/* Master MADT */
+    qemu_put_be16s(f, &s->pmsts);
+    qemu_put_be16s(f, &s->pmen);
+    qemu_put_be16s(f, &s->pmcntrl);
+    qemu_put_8s(f, &s->apmc);
+    qemu_put_8s(f, &s->apms);
+    qemu_put_timer(f, s->tmr_timer);
+    qemu_put_be64s(f, &s->tmr_overflow_time);
+}
 
-struct multiple_apic_table
+static int pm_load(QEMUFile* f,void* opaque,int version_id)
 {
-       ACPI_TABLE_HEADER_DEF                           /* ACPI common table header */
-       uint32_t                             local_apic_address;     /* Physical address of local APIC */
-#if 0
-       uint32_t                             PCATcompat      : 1;    /* A one indicates system also has dual 8259s */
-       uint32_t                             reserved1       : 31;
-#else
-        uint32_t                             flags;
-#endif
-};
-
+    PIIX4PMState *s = opaque;
+    int ret;
 
-/* Values for Type in APIC_HEADER_DEF */
+    if (version_id > 1)
+        return -EINVAL;
 
-#define APIC_PROCESSOR          0
-#define APIC_IO                 1
-#define APIC_XRUPT_OVERRIDE     2
-#define APIC_NMI                3
-#define APIC_LOCAL_NMI          4
-#define APIC_ADDRESS_OVERRIDE   5
-#define APIC_IO_SAPIC           6
-#define APIC_LOCAL_SAPIC        7
-#define APIC_XRUPT_SOURCE       8
-#define APIC_RESERVED           9           /* 9 and greater are reserved */
+    ret = pci_device_load(&s->dev, f);
+    if (ret < 0)
+        return ret;
 
-/*
- * MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE)
- */
-#define APIC_HEADER_DEF                     /* Common APIC sub-structure header */\
-       uint8_t                              type; \
-       uint8_t                              length;
+    qemu_get_be16s(f, &s->pmsts);
+    qemu_get_be16s(f, &s->pmen);
+    qemu_get_be16s(f, &s->pmcntrl);
+    qemu_get_8s(f, &s->apmc);
+    qemu_get_8s(f, &s->apms);
+    qemu_get_timer(f, s->tmr_timer);
+    qemu_get_be64s(f, &s->tmr_overflow_time);
 
-/* Sub-structures for MADT */
+    pm_io_space_update(s);
 
-struct madt_processor_apic
-{
-       APIC_HEADER_DEF
-       uint8_t                              processor_id;           /* ACPI processor id */
-       uint8_t                              local_apic_id;          /* Processor's local APIC id */
-#if 0
-       uint32_t                             processor_enabled: 1;   /* Processor is usable if set */
-       uint32_t                             reserved2       : 31;   /* Reserved, must be zero */
-#else
-        uint32_t flags;
-#endif
-};
+    return 0;
+}
 
-struct madt_io_apic
+void piix4_pm_init(PCIBus *bus, int devfn)
 {
-       APIC_HEADER_DEF
-       uint8_t                              io_apic_id;             /* I/O APIC ID */
-       uint8_t                              reserved;               /* Reserved - must be zero */
-       uint32_t                             address;                /* APIC physical address */
-       uint32_t                             interrupt;              /* Global system interrupt where INTI
-                         * lines start */
-};
+    PIIX4PMState *s;
+    uint8_t *pci_conf;
+    uint32_t pm_io_base, smb_io_base;
 
-#include "acpi-dsdt.hex"
+    s = (PIIX4PMState *)pci_register_device(bus,
+                                         "PM", sizeof(PIIX4PMState),
+                                         devfn, NULL, pm_write_config);
+    pci_conf = s->dev.config;
+    pci_conf[0x00] = 0x86;
+    pci_conf[0x01] = 0x80;
+    pci_conf[0x02] = 0x13;
+    pci_conf[0x03] = 0x71;
+    pci_conf[0x08] = 0x00; // revision number
+    pci_conf[0x09] = 0x00;
+    pci_conf[0x0a] = 0x80; // other bridge device
+    pci_conf[0x0b] = 0x06; // bridge device
+    pci_conf[0x0e] = 0x00; // header_type
+    pci_conf[0x3d] = 0x01; // interrupt pin 1
+    
+    pci_conf[0x40] = 0x01; /* PM io base read only bit */
+    
+    register_ioport_write(0xb2, 2, 1, pm_smi_writeb, s);
+    register_ioport_read(0xb2, 2, 1, pm_smi_readb, s);
 
-static int acpi_checksum(const uint8_t *data, int len)
-{
-    int sum, i;
-    sum = 0;
-    for(i = 0; i < len; i++)
-        sum += data[i];
-    return (-sum) & 0xff;
-}
+    register_ioport_write(ACPI_DBG_IO_ADDR, 4, 4, acpi_dbg_writel, s);
 
-static void acpi_build_table_header(struct acpi_table_header *h, 
-                                    char *sig, int len)
-{
-    memcpy(h->signature, sig, 4);
-    h->length = cpu_to_le32(len);
-    h->revision = 0;
-    memcpy(h->oem_id, "QEMU  ", 6);
-    memcpy(h->oem_table_id, "QEMU", 4);
-    memcpy(h->oem_table_id + 4, sig, 4);
-    h->oem_revision = cpu_to_le32(1);
-    memcpy(h->asl_compiler_id, "QEMU", 4);
-    h->asl_compiler_revision = cpu_to_le32(1);
-    h->checksum = acpi_checksum((void *)h, len);
-}
+    /* XXX: which specification is used ? The i82731AB has different
+       mappings */
+    pci_conf[0x5f] = (parallel_hds[0] != NULL ? 0x80 : 0) | 0x10;
+    pci_conf[0x63] = 0x60;
+    pci_conf[0x67] = (serial_hds[0] != NULL ? 0x08 : 0) |
+       (serial_hds[1] != NULL ? 0x90 : 0);
 
-#define ACPI_TABLES_BASE 0x000e8000
+    smb_io_base = SMB_IO_BASE;
+    pci_conf[0x90] = smb_io_base | 1;
+    pci_conf[0x91] = smb_io_base >> 8;
+    pci_conf[0xd2] = 0x09;
+    register_ioport_write(smb_io_base, 64, 1, smb_ioport_writeb, s);
+    register_ioport_read(smb_io_base, 64, 1, smb_ioport_readb, s);
 
-/* base_addr must be a multiple of 4KB */
-void acpi_bios_init(void)
-{
-    struct rsdp_descriptor *rsdp;
-    struct rsdt_descriptor_rev1 *rsdt;
-    struct fadt_descriptor_rev1 *fadt;
-    struct facs_descriptor_rev1 *facs;
-    struct multiple_apic_table *madt;
-    uint8_t *dsdt;
-    uint32_t base_addr, rsdt_addr, fadt_addr, addr, facs_addr, dsdt_addr;
-    uint32_t pm_io_base, acpi_tables_size, madt_addr, madt_size;
-    int i;
-
-    /* compute PCI I/O addresses */
-    pm_io_base = (piix4_pm_state->dev.config[0x40] | 
-        (piix4_pm_state->dev.config[0x41] << 8)) & ~0x3f;
-    
-    base_addr = ACPI_TABLES_BASE;
+    s->tmr_timer = qemu_new_timer(vm_clock, pm_tmr_timer, s);
 
-    /* reserve memory space for tables */
-    addr = base_addr;
-    rsdp = (void *)(phys_ram_base + addr);
-    addr += sizeof(*rsdp);
+    register_savevm("piix4_pm", 0, 1, pm_save, pm_load, s);
+    piix4_pm_state = s;
+}
 
-    rsdt_addr = addr;
-    rsdt = (void *)(phys_ram_base + addr);
-    addr += sizeof(*rsdt);
-    
-    fadt_addr = addr;
-    fadt = (void *)(phys_ram_base + addr);
-    addr += sizeof(*fadt);
-
-    /* XXX: FACS should be in RAM */
-    addr = (addr + 63) & ~63; /* 64 byte alignment for FACS */
-    facs_addr = addr;
-    facs = (void *)(phys_ram_base + addr);
-    addr += sizeof(*facs);
-
-    dsdt_addr = addr;
-    dsdt = (void *)(phys_ram_base + addr);
-    addr += sizeof(AmlCode);
-
-    addr = (addr + 7) & ~7;
-    madt_addr = addr;
-    madt_size = sizeof(*madt) + 
-        sizeof(struct madt_processor_apic) * smp_cpus +
-        sizeof(struct madt_io_apic);
-    madt = (void *)(phys_ram_base + addr);
-    addr += madt_size;
-
-    acpi_tables_size = addr - base_addr;
-
-    cpu_register_physical_memory(base_addr, acpi_tables_size, 
-                                 base_addr | IO_MEM_ROM);
-    
-    /* RSDP */
-    memset(rsdp, 0, sizeof(*rsdp));
-    memcpy(rsdp->signature, "RSD PTR ", 8);
-    memcpy(rsdp->oem_id, "QEMU  ", 6);
-    rsdp->rsdt_physical_address = cpu_to_le32(rsdt_addr);
-    rsdp->checksum = acpi_checksum((void *)rsdp, 20);
-    
-    /* RSDT */
-    rsdt->table_offset_entry[0] = cpu_to_le32(fadt_addr);
-    rsdt->table_offset_entry[1] = cpu_to_le32(madt_addr);
-    acpi_build_table_header((struct acpi_table_header *)rsdt, 
-                            "RSDT", sizeof(*rsdt));
-    
-    /* FADT */
-    memset(fadt, 0, sizeof(*fadt));
-    fadt->firmware_ctrl = cpu_to_le32(facs_addr);
-    fadt->dsdt = cpu_to_le32(dsdt_addr);
-    fadt->model = 1;
-    fadt->reserved1 = 0;
-    fadt->sci_int = cpu_to_le16(piix4_pm_state->dev.config[0x3c]);
-    fadt->smi_cmd = cpu_to_le32(SMI_CMD_IO_ADDR);
-    fadt->acpi_enable = 0xf1;
-    fadt->acpi_disable = 0xf0;
-    fadt->pm1a_evt_blk = cpu_to_le32(pm_io_base);
-    fadt->pm1a_cnt_blk = cpu_to_le32(pm_io_base + 0x04);
-    fadt->pm_tmr_blk = cpu_to_le32(pm_io_base + 0x08);
-    fadt->pm1_evt_len = 4;
-    fadt->pm1_cnt_len = 2;
-    fadt->pm_tmr_len = 4;
-    fadt->plvl2_lat = cpu_to_le16(50);
-    fadt->plvl3_lat = cpu_to_le16(50);
-    fadt->plvl3_lat = cpu_to_le16(50);
-    /* WBINVD + PROC_C1 + PWR_BUTTON + SLP_BUTTON + FIX_RTC */
-    fadt->flags = cpu_to_le32((1 << 0) | (1 << 2) | (1 << 4) | (1 << 5) | (1 << 6));
-    acpi_build_table_header((struct acpi_table_header *)fadt, "FACP", 
-                            sizeof(*fadt));
-
-    /* FACS */
-    memset(facs, 0, sizeof(*facs));
-    memcpy(facs->signature, "FACS", 4);
-    facs->length = cpu_to_le32(sizeof(*facs));
-
-    /* DSDT */
-    memcpy(dsdt, AmlCode, sizeof(AmlCode));
-
-    /* MADT */
-    {
-        struct madt_processor_apic *apic;
-        struct madt_io_apic *io_apic;
-
-        memset(madt, 0, madt_size);
-        madt->local_apic_address = cpu_to_le32(0xfee00000);
-        madt->flags = cpu_to_le32(1);
-        apic = (void *)(madt + 1);
-        for(i=0;i<smp_cpus;i++) {
-            apic->type = APIC_PROCESSOR;
-            apic->length = sizeof(*apic);
-            apic->processor_id = i;
-            apic->local_apic_id = i;
-            apic->flags = cpu_to_le32(1);
-            apic++;
-        }
-        io_apic = (void *)apic;
-        io_apic->type = APIC_IO;
-        io_apic->length = sizeof(*io_apic);
-        io_apic->io_apic_id = smp_cpus;
-        io_apic->address = cpu_to_le32(0xfec00000);
-        io_apic->interrupt = cpu_to_le32(0);
-
-        acpi_build_table_header((struct acpi_table_header *)madt, 
-                                "APIC", madt_size);
-    }
+void piix4_smbus_register_device(SMBusDevice *dev, uint8_t addr)
+{
+    piix4_pm_state->smb_dev[addr] = dev;
 }
index 8e08cb143a5afa6a795aabcaf88d4ed1b4560e6a..3f664a9c5e1a10c5560ef5363d622c5c9cbc9c04 100644 (file)
@@ -406,5 +406,5 @@ void adb_mouse_init(ADBBusState *bus)
     d = adb_register_device(bus, ADB_MOUSE, adb_mouse_request,
                             adb_mouse_reset, s);
     adb_mouse_reset(d);
-    qemu_add_mouse_event_handler(adb_mouse_event, d, 0);
+    qemu_add_mouse_event_handler(adb_mouse_event, d, 0, "QEMU ADB Mouse");
 }
index 02e9824b3908ca74495728033e5b9083865b0a7e..a5fe9b989e6badd9704b52b5efc5f11905d69183 100644 (file)
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
+
+/* XXX This file and most of its contests are somewhat misnamed.  The
+   Ultrasparc PCI host is called the PCI Bus Module (PBM).  The APB is
+   the secondary PCI bridge.  */
+
 #include "vl.h"
 typedef target_phys_addr_t pci_addr_t;
 #include "pci_host.h"
@@ -179,10 +184,26 @@ static CPUReadMemoryFunc *pci_apb_ioread[] = {
     &pci_apb_ioreadl,
 };
 
-/* ??? This is probably wrong.  */
-static void pci_apb_set_irq(PCIDevice *d, void *pic, int irq_num, int level)
+/* The APB host has an IRQ line for each IRQ line of each slot.  */
+static int pci_apb_map_irq(PCIDevice *pci_dev, int irq_num)
+{
+    return ((pci_dev->devfn & 0x18) >> 1) + irq_num;
+}
+
+static int pci_pbm_map_irq(PCIDevice *pci_dev, int irq_num)
 {
-    pic_set_irq_new(pic, d->config[PCI_INTERRUPT_LINE], level);
+    int bus_offset;
+    if (pci_dev->devfn & 1)
+        bus_offset = 16;
+    else
+        bus_offset = 0;
+    return bus_offset + irq_num;
+}
+
+static void pci_apb_set_irq(void *pic, int irq_num, int level)
+{
+    /* PCI IRQ map onto the first 32 INO.  */
+    pic_set_irq_new(pic, irq_num, level);
 }
 
 PCIBus *pci_apb_init(target_ulong special_base, target_ulong mem_base,
@@ -191,10 +212,12 @@ PCIBus *pci_apb_init(target_ulong special_base, target_ulong mem_base,
     APBState *s;
     PCIDevice *d;
     int pci_mem_config, pci_mem_data, apb_config, pci_ioport;
+    PCIDevice *apb;
+    PCIBus *secondary;
 
     s = qemu_mallocz(sizeof(APBState));
-    /* Ultrasparc APB main bus */
-    s->bus = pci_register_bus(pci_apb_set_irq, pic, 0);
+    /* Ultrasparc PBM main bus */
+    s->bus = pci_register_bus(pci_apb_set_irq, pci_pbm_map_irq, pic, 0, 32);
 
     pci_mem_config = cpu_register_io_memory(0, pci_apb_config_read,
                                             pci_apb_config_write, s);
@@ -211,7 +234,7 @@ PCIBus *pci_apb_init(target_ulong special_base, target_ulong mem_base,
     cpu_register_physical_memory(mem_base, 0x10000000, pci_mem_data); // XXX size should be 4G-prom
 
     d = pci_register_device(s->bus, "Advanced PCI Bus", sizeof(PCIDevice), 
-                            -1, NULL, NULL);
+                            0, NULL, NULL);
     d->config[0x00] = 0x8e; // vendor_id : Sun
     d->config[0x01] = 0x10;
     d->config[0x02] = 0x00; // device_id
@@ -226,7 +249,11 @@ PCIBus *pci_apb_init(target_ulong special_base, target_ulong mem_base,
     d->config[0x0B] = 0x06; // class_base = PCI_bridge
     d->config[0x0D] = 0x10; // latency_timer
     d->config[0x0E] = 0x00; // header_type
-    return s->bus;
+
+    /* APB secondary busses */
+    secondary = pci_bridge_init(s->bus, 8, 0x108e5000, pci_apb_map_irq, "Advanced PCI Bus secondary bridge 1");
+    pci_bridge_init(s->bus, 9, 0x108e5000, pci_apb_map_irq, "Advanced PCI Bus secondary bridge 2");
+    return secondary;
 }
 
 
index 8f88cce0116fa126be1c168371d0b8eddd9194b4..8c9776195e4ce4c98cf72c5bd3d1af3542b84e06 100644 (file)
@@ -382,8 +382,6 @@ static void apic_init_ipi(APICState *s)
 {
     int i;
 
-    for(i = 0; i < APIC_LVT_NB; i++)
-        s->lvt[i] = 1 << 16; /* mask LVT */
     s->tpr = 0;
     s->spurious_vec = 0xff;
     s->log_dest = 0;
@@ -391,7 +389,8 @@ static void apic_init_ipi(APICState *s)
     memset(s->isr, 0, sizeof(s->isr));
     memset(s->tmr, 0, sizeof(s->tmr));
     memset(s->irr, 0, sizeof(s->irr));
-    memset(s->lvt, 0, sizeof(s->lvt));
+    for(i = 0; i < APIC_LVT_NB; i++)
+        s->lvt[i] = 1 << 16; /* mask LVT */
     s->esr = 0;
     memset(s->icr, 0, sizeof(s->icr));
     s->divide_conf = 0;
@@ -477,9 +476,9 @@ int apic_get_interrupt(CPUState *env)
     intno = get_highest_priority_int(s->irr);
     if (intno < 0)
         return -1;
-    reset_bit(s->irr, intno);
     if (s->tpr && intno <= s->tpr)
         return s->spurious_vec & 0xff;
+    reset_bit(s->irr, intno);
     set_bit(s->isr, intno);
     apic_update_irq(s);
     return intno;
@@ -745,6 +744,8 @@ static void apic_save(QEMUFile *f, void *opaque)
     qemu_put_be32s(f, &s->initial_count);
     qemu_put_be64s(f, &s->initial_count_load_time);
     qemu_put_be64s(f, &s->next_time);
+
+    qemu_put_timer(f, s->timer);
 }
 
 static int apic_load(QEMUFile *f, void *opaque, int version_id)
@@ -752,7 +753,7 @@ static int apic_load(QEMUFile *f, void *opaque, int version_id)
     APICState *s = opaque;
     int i;
 
-    if (version_id != 1)
+    if (version_id > 2)
         return -EINVAL;
 
     /* XXX: what if the base changes? (registered memory regions) */
@@ -779,6 +780,9 @@ static int apic_load(QEMUFile *f, void *opaque, int version_id)
     qemu_get_be32s(f, &s->initial_count);
     qemu_get_be64s(f, &s->initial_count_load_time);
     qemu_get_be64s(f, &s->next_time);
+
+    if (version_id >= 2)
+        qemu_get_timer(f, s->timer);
     return 0;
 }
 
@@ -827,7 +831,7 @@ int apic_init(CPUState *env)
     }
     s->timer = qemu_new_timer(vm_clock, apic_timer, s);
 
-    register_savevm("apic", 0, 1, apic_save, apic_load, s);
+    register_savevm("apic", 0, 2, apic_save, apic_load, s);
     qemu_register_reset(apic_reset, s);
     
     local_apics[s->id] = s;
index 0e28d4a07aed7e3ce4f97d10743d9398fd6e25b9..28f6a92622e1d159b785d9528d6e5ece50717fca 100644 (file)
@@ -64,42 +64,52 @@ static void set_kernel_args(uint32_t ram_size, int initrd_size,
     stl_raw(p++, 0);
 }
 
-void arm_load_kernel(int ram_size, const char *kernel_filename,
+void arm_load_kernel(CPUState *env, int ram_size, const char *kernel_filename,
                      const char *kernel_cmdline, const char *initrd_filename,
                      int board_id)
 {
     int kernel_size;
     int initrd_size;
     int n;
+    uint64_t entry;
 
     /* Load the kernel.  */
     if (!kernel_filename) {
         fprintf(stderr, "Kernel image must be specified\n");
         exit(1);
     }
-    kernel_size = load_image(kernel_filename,
-                             phys_ram_base + KERNEL_LOAD_ADDR);
-    if (kernel_size < 0) {
-        fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
-        exit(1);
-    }
-    if (initrd_filename) {
-        initrd_size = load_image(initrd_filename,
-                                 phys_ram_base + INITRD_LOAD_ADDR);
-        if (initrd_size < 0) {
-            fprintf(stderr, "qemu: could not load initrd '%s'\n",
-                    initrd_filename);
+
+    kernel_size = load_elf(kernel_filename, 0, &entry);
+    if (kernel_size >= 0) {
+        /* An ELF image.  Jump to the entry point.  */
+        env->regs[15] = entry & 0xfffffffe;
+        env->thumb = entry & 1;
+    } else {
+        /* Raw binary image. Assume it is a Linux zImage.  */
+        kernel_size = load_image(kernel_filename,
+                                 phys_ram_base + KERNEL_LOAD_ADDR);
+        if (kernel_size < 0) {
+            fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
             exit(1);
         }
-    } else {
-        initrd_size = 0;
+        if (initrd_filename) {
+            initrd_size = load_image(initrd_filename,
+                                     phys_ram_base + INITRD_LOAD_ADDR);
+            if (initrd_size < 0) {
+                fprintf(stderr, "qemu: could not load initrd '%s'\n",
+                        initrd_filename);
+                exit(1);
+            }
+        } else {
+            initrd_size = 0;
+        }
+        bootloader[1] |= board_id & 0xff;
+        bootloader[2] |= (board_id >> 8) & 0xff;
+        bootloader[5] = KERNEL_ARGS_ADDR;
+        bootloader[6] = KERNEL_LOAD_ADDR;
+        for (n = 0; n < sizeof(bootloader) / 4; n++)
+            stl_raw(phys_ram_base + (n * 4), bootloader[n]);
+        set_kernel_args(ram_size, initrd_size, kernel_cmdline);
     }
-    bootloader[1] |= board_id & 0xff;
-    bootloader[2] |= (board_id >> 8) & 0xff;
-    bootloader[5] = KERNEL_ARGS_ADDR;
-    bootloader[6] = KERNEL_LOAD_ADDR;
-    for (n = 0; n < sizeof(bootloader) / 4; n++)
-        stl_raw(phys_ram_base + (n * 4), bootloader[n]);
-    set_kernel_args(ram_size, initrd_size, kernel_cmdline);
 }
 
diff --git a/tools/ioemu/hw/arm_gic.c b/tools/ioemu/hw/arm_gic.c
new file mode 100644 (file)
index 0000000..2901f34
--- /dev/null
@@ -0,0 +1,547 @@
+/* 
+ * ARM AMBA Generic/Distributed Interrupt Controller
+ *
+ * Copyright (c) 2006 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licenced under the GPL.
+ */
+
+/* TODO: Some variants of this controller can handle multiple CPUs.
+   Currently only single CPU operation is implemented.  */
+
+#include "vl.h"
+#include "arm_pic.h"
+
+//#define DEBUG_GIC
+
+#ifdef DEBUG_GIC
+#define DPRINTF(fmt, args...) \
+do { printf("arm_gic: " fmt , ##args); } while (0)
+#else
+#define DPRINTF(fmt, args...) do {} while(0)
+#endif
+
+/* Distributed interrupt controller.  */
+
+static const uint8_t gic_id[] =
+{ 0x90, 0x13, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
+
+#define GIC_NIRQ 96
+
+typedef struct gic_irq_state
+{
+    unsigned enabled:1;
+    unsigned pending:1;
+    unsigned active:1;
+    unsigned level:1;
+    unsigned model:1; /* 0 = 1:N, 1 = N:N */
+    unsigned trigger:1; /* nonzero = edge triggered.  */
+} gic_irq_state;
+
+#define GIC_SET_ENABLED(irq) s->irq_state[irq].enabled = 1
+#define GIC_CLEAR_ENABLED(irq) s->irq_state[irq].enabled = 0
+#define GIC_TEST_ENABLED(irq) s->irq_state[irq].enabled
+#define GIC_SET_PENDING(irq) s->irq_state[irq].pending = 1
+#define GIC_CLEAR_PENDING(irq) s->irq_state[irq].pending = 0
+#define GIC_TEST_PENDING(irq) s->irq_state[irq].pending
+#define GIC_SET_ACTIVE(irq) s->irq_state[irq].active = 1
+#define GIC_CLEAR_ACTIVE(irq) s->irq_state[irq].active = 0
+#define GIC_TEST_ACTIVE(irq) s->irq_state[irq].active
+#define GIC_SET_MODEL(irq) s->irq_state[irq].model = 1
+#define GIC_CLEAR_MODEL(irq) s->irq_state[irq].model = 0
+#define GIC_TEST_MODEL(irq) s->irq_state[irq].model
+#define GIC_SET_LEVEL(irq) s->irq_state[irq].level = 1
+#define GIC_CLEAR_LEVEL(irq) s->irq_state[irq].level = 0
+#define GIC_TEST_LEVEL(irq) s->irq_state[irq].level
+#define GIC_SET_TRIGGER(irq) s->irq_state[irq].trigger = 1
+#define GIC_CLEAR_TRIGGER(irq) s->irq_state[irq].trigger = 0
+#define GIC_TEST_TRIGGER(irq) s->irq_state[irq].trigger
+
+typedef struct gic_state
+{
+    arm_pic_handler handler;
+    uint32_t base;
+    void *parent;
+    int parent_irq;
+    int enabled;
+    int cpu_enabled;
+
+    gic_irq_state irq_state[GIC_NIRQ];
+    int irq_target[GIC_NIRQ];
+    int priority[GIC_NIRQ];
+    int last_active[GIC_NIRQ];
+
+    int priority_mask;
+    int running_irq;
+    int running_priority;
+    int current_pending;
+} gic_state;
+
+/* TODO: Many places that call this routine could be optimized.  */
+/* Update interrupt status after enabled or pending bits have been changed.  */
+static void gic_update(gic_state *s)
+{
+    int best_irq;
+    int best_prio;
+    int irq;
+
+    s->current_pending = 1023;
+    if (!s->enabled || !s->cpu_enabled) {
+        pic_set_irq_new(s->parent, s->parent_irq, 0);
+        return;
+    }
+    best_prio = 0x100;
+    best_irq = 1023;
+    for (irq = 0; irq < 96; irq++) {
+        if (GIC_TEST_ENABLED(irq) && GIC_TEST_PENDING(irq)) {
+            if (s->priority[irq] < best_prio) {
+                best_prio = s->priority[irq];
+                best_irq = irq;
+            }
+        }
+    }
+    if (best_prio > s->priority_mask) {
+        pic_set_irq_new(s->parent, s->parent_irq, 0);
+    } else {
+        s->current_pending = best_irq;
+        if (best_prio < s->running_priority) {
+            DPRINTF("Raised pending IRQ %d\n", best_irq);
+            pic_set_irq_new(s->parent, s->parent_irq, 1);
+        }
+    }
+}
+
+static void gic_set_irq(void *opaque, int irq, int level)
+{
+    gic_state *s = (gic_state *)opaque;
+    /* The first external input line is internal interrupt 32.  */
+    irq += 32;
+    if (level == GIC_TEST_LEVEL(irq)) 
+        return;
+
+    if (level) {
+        GIC_SET_LEVEL(irq);
+        if (GIC_TEST_TRIGGER(irq) || GIC_TEST_ENABLED(irq)) {
+            DPRINTF("Set %d pending\n", irq);
+            GIC_SET_PENDING(irq);
+        }
+    } else {
+        GIC_CLEAR_LEVEL(irq);
+    }
+    gic_update(s);
+}
+
+static void gic_set_running_irq(gic_state *s, int irq)
+{
+    s->running_irq = irq;
+    if (irq == 1023)
+        s->running_priority = 0x100;
+    else
+        s->running_priority = s->priority[irq];
+    gic_update(s);
+}
+
+static uint32_t gic_acknowledge_irq(gic_state *s)
+{
+    int new_irq;
+    new_irq = s->current_pending;
+    if (new_irq == 1023 || s->priority[new_irq] >= s->running_priority) {
+        DPRINTF("ACK no pending IRQ\n");
+        return 1023;
+    }
+    pic_set_irq_new(s->parent, s->parent_irq, 0);
+    s->last_active[new_irq] = s->running_irq;
+    /* For level triggered interrupts we clear the pending bit while
+       the interrupt is active.  */
+    GIC_CLEAR_PENDING(new_irq);
+    gic_set_running_irq(s, new_irq);
+    DPRINTF("ACK %d\n", new_irq);
+    return new_irq;
+}
+
+static void gic_complete_irq(gic_state * s, int irq)
+{
+    int update = 0;
+    DPRINTF("EOI %d\n", irq);
+    if (s->running_irq == 1023)
+        return; /* No active IRQ.  */
+    if (irq != 1023) {
+        /* Mark level triggered interrupts as pending if they are still
+           raised.  */
+        if (!GIC_TEST_TRIGGER(irq) && GIC_TEST_ENABLED(irq)
+                && GIC_TEST_LEVEL(irq)) {
+            GIC_SET_PENDING(irq);
+            update = 1;
+        }
+    }
+    if (irq != s->running_irq) {
+        /* Complete an IRQ that is not currently running.  */
+        int tmp = s->running_irq;
+        while (s->last_active[tmp] != 1023) {
+            if (s->last_active[tmp] == irq) {
+                s->last_active[tmp] = s->last_active[irq];
+                break;
+            }
+            tmp = s->last_active[tmp];
+        }
+        if (update) {
+            gic_update(s);
+        }
+    } else {
+        /* Complete the current running IRQ.  */
+        gic_set_running_irq(s, s->last_active[s->running_irq]);
+    }
+}
+
+static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
+{
+    gic_state *s = (gic_state *)opaque;
+    uint32_t res;
+    int irq;
+    int i;
+
+    offset -= s->base + 0x1000;
+    if (offset < 0x100) {
+        if (offset == 0)
+            return s->enabled;
+        if (offset == 4)
+            return (GIC_NIRQ / 32) - 1;
+        if (offset < 0x08)
+            return 0;
+        goto bad_reg;
+    } else if (offset < 0x200) {
+        /* Interrupt Set/Clear Enable.  */
+        if (offset < 0x180)
+            irq = (offset - 0x100) * 8;
+        else
+            irq = (offset - 0x180) * 8;
+        if (irq >= GIC_NIRQ)
+            goto bad_reg;
+        res = 0;
+        for (i = 0; i < 8; i++) {
+            if (GIC_TEST_ENABLED(irq + i)) {
+                res |= (1 << i);
+            }
+        }
+    } else if (offset < 0x300) {
+        /* Interrupt Set/Clear Pending.  */
+        if (offset < 0x280)
+            irq = (offset - 0x200) * 8;
+        else
+            irq = (offset - 0x280) * 8;
+        if (irq >= GIC_NIRQ)
+            goto bad_reg;
+        res = 0;
+        for (i = 0; i < 8; i++) {
+            if (GIC_TEST_PENDING(irq + i)) {
+                res |= (1 << i);
+            }
+        }
+    } else if (offset < 0x400) {
+        /* Interrupt Active.  */
+        irq = (offset - 0x300) * 8;
+        if (irq >= GIC_NIRQ)
+            goto bad_reg;
+        res = 0;
+        for (i = 0; i < 8; i++) {
+            if (GIC_TEST_ACTIVE(irq + i)) {
+                res |= (1 << i);
+            }
+        }
+    } else if (offset < 0x800) {
+        /* Interrupt Priority.  */
+        irq = offset - 0x400;
+        if (irq >= GIC_NIRQ)
+            goto bad_reg;
+        res = s->priority[irq];
+    } else if (offset < 0xc00) {
+        /* Interrupt CPU Target.  */
+        irq = offset - 0x800;
+        if (irq >= GIC_NIRQ)
+            goto bad_reg;
+        res = s->irq_target[irq];
+    } else if (offset < 0xf00) {
+        /* Interrupt Configuration.  */
+        irq = (offset - 0xc00) * 2;
+        if (irq >= GIC_NIRQ)
+            goto bad_reg;
+        res = 0;
+        for (i = 0; i < 4; i++) {
+            if (GIC_TEST_MODEL(irq + i))
+                res |= (1 << (i * 2));
+            if (GIC_TEST_TRIGGER(irq + i))
+                res |= (2 << (i * 2));
+        }
+    } else if (offset < 0xfe0) {
+        goto bad_reg;
+    } else /* offset >= 0xfe0 */ {
+        if (offset & 3) {
+            res = 0;
+        } else {
+            res = gic_id[(offset - 0xfe0) >> 2];
+        }
+    }
+    return res;
+bad_reg:
+    cpu_abort (cpu_single_env, "gic_dist_readb: Bad offset %x\n", offset);
+    return 0;
+}
+
+static uint32_t gic_dist_readw(void *opaque, target_phys_addr_t offset)
+{
+    uint32_t val;
+    val = gic_dist_readb(opaque, offset);
+    val |= gic_dist_readb(opaque, offset + 1) << 8;
+    return val;
+}
+
+static uint32_t gic_dist_readl(void *opaque, target_phys_addr_t offset)
+{
+    uint32_t val;
+    val = gic_dist_readw(opaque, offset);
+    val |= gic_dist_readw(opaque, offset + 2) << 16;
+    return val;
+}
+
+static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
+                            uint32_t value)
+{
+    gic_state *s = (gic_state *)opaque;
+    int irq;
+    int i;
+
+    offset -= s->base + 0x1000;
+    if (offset < 0x100) {
+        if (offset == 0) {
+            s->enabled = (value & 1);
+            DPRINTF("Distribution %sabled\n", s->enabled ? "En" : "Dis");
+        } else if (offset < 4) {
+            /* ignored.  */
+        } else {
+            goto bad_reg;
+        }
+    } else if (offset < 0x180) {
+        /* Interrupt Set Enable.  */
+        irq = (offset - 0x100) * 8;
+        if (irq >= GIC_NIRQ)
+            goto bad_reg;
+        for (i = 0; i < 8; i++) {
+            if (value & (1 << i)) {
+                if (!GIC_TEST_ENABLED(irq + i))
+                    DPRINTF("Enabled IRQ %d\n", irq + i);
+                GIC_SET_ENABLED(irq + i);
+                /* If a raised level triggered IRQ enabled then mark
+                   is as pending.  */
+                if (GIC_TEST_LEVEL(irq + i) && !GIC_TEST_TRIGGER(irq + i))
+                    GIC_SET_PENDING(irq + i);
+            }
+        }
+    } else if (offset < 0x200) {
+        /* Interrupt Clear Enable.  */
+        irq = (offset - 0x180) * 8;
+        if (irq >= GIC_NIRQ)
+            goto bad_reg;
+        for (i = 0; i < 8; i++) {
+            if (value & (1 << i)) {
+                if (GIC_TEST_ENABLED(irq + i))
+                    DPRINTF("Disabled IRQ %d\n", irq + i);
+                GIC_CLEAR_ENABLED(irq + i);
+            }
+        }
+    } else if (offset < 0x280) {
+        /* Interrupt Set Pending.  */
+        irq = (offset - 0x200) * 8;
+        if (irq >= GIC_NIRQ)
+            goto bad_reg;
+        for (i = 0; i < 8; i++) {
+            if (value & (1 << i)) {
+                GIC_SET_PENDING(irq + i);
+            }
+        }
+    } else if (offset < 0x300) {
+        /* Interrupt Clear Pending.  */
+        irq = (offset - 0x280) * 8;
+        if (irq >= GIC_NIRQ)
+            goto bad_reg;
+        for (i = 0; i < 8; i++) {
+            if (value & (1 << i)) {
+                GIC_CLEAR_PENDING(irq + i);
+            }
+        }
+    } else if (offset < 0x400) {
+        /* Interrupt Active.  */
+        goto bad_reg;
+    } else if (offset < 0x800) {
+        /* Interrupt Priority.  */
+        irq = offset - 0x400;
+        if (irq >= GIC_NIRQ)
+            goto bad_reg;
+        s->priority[irq] = value;
+    } else if (offset < 0xc00) {
+        /* Interrupt CPU Target.  */
+        irq = offset - 0x800;
+        if (irq >= GIC_NIRQ)
+            goto bad_reg;
+        s->irq_target[irq] = value;
+    } else if (offset < 0xf00) {
+        /* Interrupt Configuration.  */
+        irq = (offset - 0xc00) * 4;
+        if (irq >= GIC_NIRQ)
+            goto bad_reg;
+        for (i = 0; i < 4; i++) {
+            if (value & (1 << (i * 2))) {
+                GIC_SET_MODEL(irq + i);
+            } else {
+                GIC_CLEAR_MODEL(irq + i);
+            }
+            if (value & (2 << (i * 2))) {
+                GIC_SET_TRIGGER(irq + i);
+            } else {
+                GIC_CLEAR_TRIGGER(irq + i);
+            }
+        }
+    } else {
+        /* 0xf00 is only handled for word writes.  */
+        goto bad_reg;
+    }
+    gic_update(s);
+    return;
+bad_reg:
+    cpu_abort (cpu_single_env, "gic_dist_writeb: Bad offset %x\n", offset);
+}
+
+static void gic_dist_writew(void *opaque, target_phys_addr_t offset,
+                            uint32_t value)
+{
+    gic_state *s = (gic_state *)opaque;
+    if (offset - s->base == 0xf00) {
+        GIC_SET_PENDING(value & 0x3ff);
+        gic_update(s);
+        return;
+    }
+    gic_dist_writeb(opaque, offset, value & 0xff);
+    gic_dist_writeb(opaque, offset + 1, value >> 8);
+}
+
+static void gic_dist_writel(void *opaque, target_phys_addr_t offset,
+                            uint32_t value)
+{
+    gic_dist_writew(opaque, offset, value & 0xffff);
+    gic_dist_writew(opaque, offset + 2, value >> 16);
+}
+
+static CPUReadMemoryFunc *gic_dist_readfn[] = {
+   gic_dist_readb,
+   gic_dist_readw,
+   gic_dist_readl
+};
+
+static CPUWriteMemoryFunc *gic_dist_writefn[] = {
+   gic_dist_writeb,
+   gic_dist_writew,
+   gic_dist_writel
+};
+
+static uint32_t gic_cpu_read(void *opaque, target_phys_addr_t offset)
+{
+    gic_state *s = (gic_state *)opaque;
+    offset -= s->base;
+    switch (offset) {
+    case 0x00: /* Control */
+        return s->cpu_enabled;
+    case 0x04: /* Priority mask */
+        return s->priority_mask;
+    case 0x08: /* Binary Point */
+        /* ??? Not implemented.  */
+        return 0;
+    case 0x0c: /* Acknowledge */
+        return gic_acknowledge_irq(s);
+    case 0x14: /* Runing Priority */
+        return s->running_priority;
+    case 0x18: /* Highest Pending Interrupt */
+        return s->current_pending;
+    default:
+        cpu_abort (cpu_single_env, "gic_cpu_writeb: Bad offset %x\n", offset);
+        return 0;
+    }
+}
+
+static void gic_cpu_write(void *opaque, target_phys_addr_t offset,
+                          uint32_t value)
+{
+    gic_state *s = (gic_state *)opaque;
+    offset -= s->base;
+    switch (offset) {
+    case 0x00: /* Control */
+        s->cpu_enabled = (value & 1);
+        DPRINTF("CPU %sabled\n", s->cpu_enabled ? "En" : "Dis");
+        break;
+    case 0x04: /* Priority mask */
+        s->priority_mask = (value & 0x3ff);
+        break;
+    case 0x08: /* Binary Point */
+        /* ??? Not implemented.  */
+        break;
+    case 0x10: /* End Of Interrupt */
+        return gic_complete_irq(s, value & 0x3ff);
+    default:
+        cpu_abort (cpu_single_env, "gic_cpu_writeb: Bad offset %x\n", offset);
+        return;
+    }
+    gic_update(s);
+}
+
+static CPUReadMemoryFunc *gic_cpu_readfn[] = {
+   gic_cpu_read,
+   gic_cpu_read,
+   gic_cpu_read
+};
+
+static CPUWriteMemoryFunc *gic_cpu_writefn[] = {
+   gic_cpu_write,
+   gic_cpu_write,
+   gic_cpu_write
+};
+
+static void gic_reset(gic_state *s)
+{
+    int i;
+    memset(s->irq_state, 0, GIC_NIRQ * sizeof(gic_irq_state));
+    s->priority_mask = 0xf0;
+    s->current_pending = 1023;
+    s->running_irq = 1023;
+    s->running_priority = 0x100;
+    for (i = 0; i < 15; i++) {
+        GIC_SET_ENABLED(i);
+        GIC_SET_TRIGGER(i);
+    }
+    s->enabled = 0;
+    s->cpu_enabled = 0;
+}
+
+void *arm_gic_init(uint32_t base, void *parent, int parent_irq)
+{
+    gic_state *s;
+    int iomemtype;
+
+    s = (gic_state *)qemu_mallocz(sizeof(gic_state));
+    if (!s)
+        return NULL;
+    s->handler = gic_set_irq;
+    s->parent = parent;
+    s->parent_irq = parent_irq;
+    if (base != 0xffffffff) {
+        iomemtype = cpu_register_io_memory(0, gic_cpu_readfn,
+                                           gic_cpu_writefn, s);
+        cpu_register_physical_memory(base, 0x00000fff, iomemtype);
+        iomemtype = cpu_register_io_memory(0, gic_dist_readfn,
+                                           gic_dist_writefn, s);
+        cpu_register_physical_memory(base + 0x1000, 0x00000fff, iomemtype);
+        s->base = base;
+    } else {
+        s->base = 0;
+    }
+    gic_reset(s);
+    return s;
+}
diff --git a/tools/ioemu/hw/arm_sysctl.c b/tools/ioemu/hw/arm_sysctl.c
new file mode 100644 (file)
index 0000000..e9de998
--- /dev/null
@@ -0,0 +1,208 @@
+/* 
+ * Status and system control registers for ARM RealView/Versatile boards.
+ *
+ * Copyright (c) 2006 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licenced under the GPL.
+ */
+
+#include "vl.h"
+#include "arm_pic.h"
+
+#define LOCK_VALUE 0xa05f
+
+typedef struct {
+    uint32_t base;
+    uint32_t sys_id;
+    uint32_t leds;
+    uint16_t lockval;
+    uint32_t cfgdata1;
+    uint32_t cfgdata2;
+    uint32_t flags;
+    uint32_t nvflags;
+    uint32_t resetlevel;
+} arm_sysctl_state;
+
+static uint32_t arm_sysctl_read(void *opaque, target_phys_addr_t offset)
+{
+    arm_sysctl_state *s = (arm_sysctl_state *)opaque;
+
+    offset -= s->base;
+    switch (offset) {
+    case 0x00: /* ID */
+        return s->sys_id;
+    case 0x04: /* SW */
+        /* General purpose hardware switches.
+           We don't have a useful way of exposing these to the user.  */
+        return 0;
+    case 0x08: /* LED */
+        return s->leds;
+    case 0x20: /* LOCK */
+        return s->lockval;
+    case 0x0c: /* OSC0 */
+    case 0x10: /* OSC1 */
+    case 0x14: /* OSC2 */
+    case 0x18: /* OSC3 */
+    case 0x1c: /* OSC4 */
+    case 0x24: /* 100HZ */
+        /* ??? Implement these.  */
+        return 0;
+    case 0x28: /* CFGDATA1 */
+        return s->cfgdata1;
+    case 0x2c: /* CFGDATA2 */
+        return s->cfgdata2;
+    case 0x30: /* FLAGS */
+        return s->flags;
+    case 0x38: /* NVFLAGS */
+        return s->nvflags;
+    case 0x40: /* RESETCTL */
+        return s->resetlevel;
+    case 0x44: /* PCICTL */
+        return 1;
+    case 0x48: /* MCI */
+        return 0;
+    case 0x4c: /* FLASH */
+        return 0;
+    case 0x50: /* CLCD */
+        return 0x1000;
+    case 0x54: /* CLCDSER */
+        return 0;
+    case 0x58: /* BOOTCS */
+        return 0;
+    case 0x5c: /* 24MHz */
+        /* ??? not implemented.  */
+        return 0;
+    case 0x60: /* MISC */
+        return 0;
+    case 0x84: /* PROCID0 */
+        /* ??? Don't know what the proper value for the core tile ID is.  */
+        return 0x02000000;
+    case 0x88: /* PROCID1 */
+        return 0xff000000;
+    case 0x64: /* DMAPSR0 */
+    case 0x68: /* DMAPSR1 */
+    case 0x6c: /* DMAPSR2 */
+    case 0x70: /* IOSEL */
+    case 0x74: /* PLDCTL */
+    case 0x80: /* BUSID */
+    case 0x8c: /* OSCRESET0 */
+    case 0x90: /* OSCRESET1 */
+    case 0x94: /* OSCRESET2 */
+    case 0x98: /* OSCRESET3 */
+    case 0x9c: /* OSCRESET4 */
+    case 0xc0: /* SYS_TEST_OSC0 */
+    case 0xc4: /* SYS_TEST_OSC1 */
+    case 0xc8: /* SYS_TEST_OSC2 */
+    case 0xcc: /* SYS_TEST_OSC3 */
+    case 0xd0: /* SYS_TEST_OSC4 */
+        return 0;
+    default:
+        printf ("arm_sysctl_read: Bad register offset 0x%x\n", (int)offset);
+        return 0;
+    }
+}
+
+static void arm_sysctl_write(void *opaque, target_phys_addr_t offset,
+                          uint32_t val)
+{
+    arm_sysctl_state *s = (arm_sysctl_state *)opaque;
+    offset -= s->base;
+
+    switch (offset) {
+    case 0x08: /* LED */
+        s->leds = val;
+    case 0x0c: /* OSC0 */
+    case 0x10: /* OSC1 */
+    case 0x14: /* OSC2 */
+    case 0x18: /* OSC3 */
+    case 0x1c: /* OSC4 */
+        /* ??? */
+        break;
+    case 0x20: /* LOCK */
+        if (val == LOCK_VALUE)
+            s->lockval = val;
+        else
+            s->lockval = val & 0x7fff;
+        break;
+    case 0x28: /* CFGDATA1 */
+        /* ??? Need to implement this.  */
+        s->cfgdata1 = val;
+        break;
+    case 0x2c: /* CFGDATA2 */
+        /* ??? Need to implement this.  */
+        s->cfgdata2 = val;
+        break;
+    case 0x30: /* FLAGSSET */
+        s->flags |= val;
+        break;
+    case 0x34: /* FLAGSCLR */
+        s->flags &= ~val;
+        break;
+    case 0x38: /* NVFLAGSSET */
+        s->nvflags |= val;
+        break;
+    case 0x3c: /* NVFLAGSCLR */
+        s->nvflags &= ~val;
+        break;
+    case 0x40: /* RESETCTL */
+        if (s->lockval == LOCK_VALUE) {
+            s->resetlevel = val;
+            if (val & 0x100)
+                cpu_abort(cpu_single_env, "Board reset\n");
+        }
+        break;
+    case 0x44: /* PCICTL */
+        /* nothing to do.  */
+        break;
+    case 0x4c: /* FLASH */
+    case 0x50: /* CLCD */
+    case 0x54: /* CLCDSER */
+    case 0x64: /* DMAPSR0 */
+    case 0x68: /* DMAPSR1 */
+    case 0x6c: /* DMAPSR2 */
+    case 0x70: /* IOSEL */
+    case 0x74: /* PLDCTL */
+    case 0x80: /* BUSID */
+    case 0x84: /* PROCID0 */
+    case 0x88: /* PROCID1 */
+    case 0x8c: /* OSCRESET0 */
+    case 0x90: /* OSCRESET1 */
+    case 0x94: /* OSCRESET2 */
+    case 0x98: /* OSCRESET3 */
+    case 0x9c: /* OSCRESET4 */
+        break;
+    default:
+        printf ("arm_sysctl_write: Bad register offset 0x%x\n", (int)offset);
+        return;
+    }
+}
+
+static CPUReadMemoryFunc *arm_sysctl_readfn[] = {
+   arm_sysctl_read,
+   arm_sysctl_read,
+   arm_sysctl_read
+};
+
+static CPUWriteMemoryFunc *arm_sysctl_writefn[] = {
+   arm_sysctl_write,
+   arm_sysctl_write,
+   arm_sysctl_write
+};
+
+void arm_sysctl_init(uint32_t base, uint32_t sys_id)
+{
+    arm_sysctl_state *s;
+    int iomemtype;
+
+    s = (arm_sysctl_state *)qemu_mallocz(sizeof(arm_sysctl_state));
+    if (!s)
+        return;
+    s->base = base;
+    s->sys_id = sys_id;
+    iomemtype = cpu_register_io_memory(0, arm_sysctl_readfn,
+                                       arm_sysctl_writefn, s);
+    cpu_register_physical_memory(base, 0x00000fff, iomemtype);
+    /* ??? Save/restore.  */
+}
+
index a97d73e4474d9f8f4fac46d927b915c00f66f744..c8864f13ce5f1d64925ce743814c9bfce57ac527 100644 (file)
@@ -107,29 +107,29 @@ static void arm_timer_update(arm_timer_state *s, int64_t now)
 /* Return the current value of the timer.  */
 static uint32_t arm_timer_getcount(arm_timer_state *s, int64_t now)
 {
-    int64_t elapsed;
+    int64_t left;
     int64_t period;
 
     if (s->count == 0)
         return 0;
     if ((s->control & TIMER_CTRL_ENABLE) == 0)
         return s->count;
-    elapsed = now - s->loaded;
+    left = s->expires - now;
     period = s->expires - s->loaded;
     /* If the timer should have expired then return 0.  This can happen
        when the host timer signal doesnt occur immediately.  It's better to
        have a timer appear to sit at zero for a while than have it wrap
        around before the guest interrupt is raised.  */
     /* ??? Could we trigger the interrupt here?  */
-    if (elapsed > period)
+    if (left < 0)
         return 0;
     /* We need to calculate count * elapsed / period without overfowing.
        Scale both elapsed and period so they fit in a 32-bit int.  */
     while (period != (int32_t)period) {
         period >>= 1;
-        elapsed >>= 1;
+        left >>= 1;
     }
-    return ((uint64_t)s->count * (uint64_t)(int32_t)elapsed)
+    return ((uint64_t)s->count * (uint64_t)(int32_t)left)
             / (int32_t)period;
 }
 
index 4e325ba6ce2bb88b702c236d05e93df0c2aa1936..96f7cbb007c24c2bbe84c8021d1ca21f5908905c 100644 (file)
@@ -1010,12 +1010,12 @@ static void cirrus_write_bitblt(CirrusVGAState * s, unsigned reg_value)
  ***************************************/
 
 static void cirrus_get_offsets(VGAState *s1, 
-                                   uint32_t *pline_offset,
-                                   uint32_t *pstart_addr)
+                               uint32_t *pline_offset,
+                               uint32_t *pstart_addr,
+                               uint32_t *pline_compare)
 {
     CirrusVGAState * s = (CirrusVGAState *)s1;
-    uint32_t start_addr;
-    uint32_t line_offset;
+    uint32_t start_addr, line_offset, line_compare;
 
     line_offset = s->cr[0x13]
        | ((s->cr[0x1b] & 0x10) << 4);
@@ -1028,6 +1028,11 @@ static void cirrus_get_offsets(VGAState *s1,
        | ((s->cr[0x1b] & 0x0c) << 15)
        | ((s->cr[0x1d] & 0x80) << 12);
     *pstart_addr = start_addr;
+
+    line_compare = s->cr[0x18] | 
+        ((s->cr[0x07] & 0x10) << 4) |
+        ((s->cr[0x09] & 0x40) << 3);
+    *pline_compare = line_compare;
 }
 
 static uint32_t cirrus_get_bpp16_depth(CirrusVGAState * s)
@@ -3049,6 +3054,9 @@ static void cirrus_vga_save(QEMUFile *f, void *opaque)
     CirrusVGAState *s = opaque;
     uint8_t vga_acc;
 
+    if (s->pci_dev)
+        pci_device_save(s->pci_dev, f);
+
     qemu_put_be32s(f, &s->latch);
     qemu_put_8s(f, &s->sr_index);
     qemu_put_buffer(f, s->sr, 256);
@@ -3096,10 +3104,17 @@ static int cirrus_vga_load(QEMUFile *f, void *opaque, int version_id)
 {
     CirrusVGAState *s = opaque;
     uint8_t vga_acc = 0;
+    int ret;
 
-    if (version_id != 1)
+    if (version_id > 2)
         return -EINVAL;
 
+    if (s->pci_dev && version_id >= 2) {
+        ret = pci_device_load(s->pci_dev, f);
+        if (ret < 0)
+            return ret;
+    }
+
     qemu_get_be32s(f, &s->latch);
     qemu_get_8s(f, &s->sr_index);
     qemu_get_buffer(f, s->sr, 256);
@@ -3261,7 +3276,7 @@ static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci)
     s->cursor_invalidate = cirrus_cursor_invalidate;
     s->cursor_draw_line = cirrus_cursor_draw_line;
 
-    register_savevm("cirrus_vga", 0, 1, cirrus_vga_save, cirrus_vga_load, s);
+    register_savevm("cirrus_vga", 0, 2, cirrus_vga_save, cirrus_vga_load, s);
 }
 
 /***************************************
@@ -3350,8 +3365,7 @@ void pci_cirrus_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
     vga_common_init((VGAState *)s, 
                     ds, vga_ram_base, vga_ram_offset, vga_ram_size);
     cirrus_init_common(s, device_id, 1);
-
-    register_savevm("cirrus_vga_pci", 0, 1, generic_pci_save, generic_pci_load, d);
+    s->pci_dev = (PCIDevice *)d;
 
     /* setup memory space */
     /* memory #0 LFB */
diff --git a/tools/ioemu/hw/cs4231.c b/tools/ioemu/hw/cs4231.c
new file mode 100644 (file)
index 0000000..a154685
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ * QEMU Crystal CS4231 audio chip emulation
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+
+/* debug CS4231 */
+//#define DEBUG_CS
+
+/*
+ * In addition to Crystal CS4231 there is a DMA controller on Sparc.
+ */
+#define CS_MAXADDR 0x3f
+#define CS_REGS 16
+#define CS_DREGS 32
+#define CS_MAXDREG (CS_DREGS - 1)
+
+typedef struct CSState {
+    uint32_t regs[CS_REGS];
+    uint8_t dregs[CS_DREGS];
+    void *intctl;
+} CSState;
+
+#define CS_RAP(s) ((s)->regs[0] & CS_MAXDREG)
+#define CS_VER 0xa0
+#define CS_CDC_VER 0x8a
+
+#ifdef DEBUG_CS
+#define DPRINTF(fmt, args...)                           \
+    do { printf("CS: " fmt , ##args); } while (0)
+#define pic_set_irq_new(intctl, irq, level)                             \
+    do { printf("CS: set_irq(%d): %d\n", (irq), (level));               \
+        pic_set_irq_new((intctl), (irq),(level));} while (0)
+#else
+#define DPRINTF(fmt, args...)
+#endif
+
+static void cs_reset(void *opaque)
+{
+    CSState *s = opaque;
+
+    memset(s->regs, 0, CS_REGS * 4);
+    memset(s->dregs, 0, CS_DREGS);
+    s->dregs[12] = CS_CDC_VER;
+    s->dregs[25] = CS_VER;
+}
+
+static uint32_t cs_mem_readl(void *opaque, target_phys_addr_t addr)
+{
+    CSState *s = opaque;
+    uint32_t saddr, ret;
+
+    saddr = (addr & CS_MAXADDR) >> 2;
+    switch (saddr) {
+    case 1:
+        switch (CS_RAP(s)) {
+        case 3: // Write only
+            ret = 0;
+            break;
+        default:
+            ret = s->dregs[CS_RAP(s)];
+            break;
+        }
+        DPRINTF("read dreg[%d]: 0x%8.8x\n", CS_RAP(s), ret);
+       break;
+    default:
+        ret = s->regs[saddr];
+        DPRINTF("read reg[%d]: 0x%8.8x\n", saddr, ret);
+       break;
+    }
+    return ret;
+}
+
+static void cs_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+    CSState *s = opaque;
+    uint32_t saddr;
+
+    saddr = (addr & CS_MAXADDR) >> 2;
+    DPRINTF("write reg[%d]: 0x%8.8x -> 0x%8.8x\n", saddr, s->regs[saddr], val);
+    switch (saddr) {
+    case 1:
+        DPRINTF("write dreg[%d]: 0x%2.2x -> 0x%2.2x\n", CS_RAP(s), s->dregs[CS_RAP(s)], val);
+        switch(CS_RAP(s)) {
+        case 11:
+        case 25: // Read only
+            break;
+        case 12:
+            val &= 0x40;
+            val |= CS_CDC_VER; // Codec version
+            s->dregs[CS_RAP(s)] = val;
+            break;
+        default:
+            s->dregs[CS_RAP(s)] = val;
+            break;
+        }
+        break;
+    case 2: // Read only
+        break;
+    case 4:
+        if (val & 1)
+            cs_reset(s);
+        val &= 0x7f;
+        s->regs[saddr] = val;
+        break;
+    default:
+        s->regs[saddr] = val;
+       break;
+    }
+}
+
+static CPUReadMemoryFunc *cs_mem_read[3] = {
+    cs_mem_readl,
+    cs_mem_readl,
+    cs_mem_readl,
+};
+
+static CPUWriteMemoryFunc *cs_mem_write[3] = {
+    cs_mem_writel,
+    cs_mem_writel,
+    cs_mem_writel,
+};
+
+static void cs_save(QEMUFile *f, void *opaque)
+{
+    CSState *s = opaque;
+    unsigned int i;
+
+    for (i = 0; i < CS_REGS; i++)
+        qemu_put_be32s(f, &s->regs[i]);
+
+    qemu_put_buffer(f, s->dregs, CS_DREGS);
+}
+
+static int cs_load(QEMUFile *f, void *opaque, int version_id)
+{
+    CSState *s = opaque;
+    unsigned int i;
+
+    if (version_id > 1)
+        return -EINVAL;
+
+    for (i = 0; i < CS_REGS; i++)
+        qemu_get_be32s(f, &s->regs[i]);
+
+    qemu_get_buffer(f, s->dregs, CS_DREGS);
+    return 0;
+}
+
+void cs_init(target_phys_addr_t base, int irq, void *intctl)
+{
+    int cs_io_memory;
+    CSState *s;
+
+    s = qemu_mallocz(sizeof(CSState));
+    if (!s)
+        return;
+
+    cs_io_memory = cpu_register_io_memory(0, cs_mem_read, cs_mem_write, s);
+    cpu_register_physical_memory(base, CS_MAXADDR, cs_io_memory);
+    register_savevm("cs4231", base, 1, cs_save, cs_load, s);
+    qemu_register_reset(cs_reset, s);
+    cs_reset(s);
+}
index cdd062f7894d77339888e5b771813ba00b8507b9..fea08d87836c7133de955acc003aa107b3371290 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * QEMU ESP emulation
+ * QEMU ESP/NCR53C9x emulation
  * 
  * Copyright (c) 2005-2006 Fabrice Bellard
  * 
 /* debug ESP card */
 //#define DEBUG_ESP
 
+/*
+ * On Sparc32, this is the ESP (NCR53C90) part of chip STP2000 (Master I/O), also
+ * produced as NCR89C100. See
+ * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C100.txt
+ * and
+ * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR53C9X.txt
+ */
+
 #ifdef DEBUG_ESP
 #define DPRINTF(fmt, args...) \
 do { printf("ESP: " fmt , ##args); } while (0)
-#define pic_set_irq(irq, level) \
-do { printf("ESP: set_irq(%d): %d\n", (irq), (level)); pic_set_irq((irq),(level));} while (0)
 #else
 #define DPRINTF(fmt, args...)
 #endif
 
-#define ESPDMA_REGS 4
-#define ESPDMA_MAXADDR (ESPDMA_REGS * 4 - 1)
 #define ESP_MAXREG 0x3f
 #define TI_BUFSZ 32
-#define DMA_VER 0xa0000000
-#define DMA_INTR 1
-#define DMA_INTREN 0x10
-#define DMA_WRITE_MEM 0x100
-#define DMA_LOADED 0x04000000
+/* The HBA is ID 7, so for simplicitly limit to 7 devices.  */
+#define ESP_MAX_DEVS      7
+
 typedef struct ESPState ESPState;
 
 struct ESPState {
     BlockDriverState **bd;
     uint8_t rregs[ESP_MAXREG];
     uint8_t wregs[ESP_MAXREG];
-    int irq;
-    uint32_t espdmaregs[ESPDMA_REGS];
-    uint32_t ti_size;
+    int32_t ti_size;
     uint32_t ti_rptr, ti_wptr;
     uint8_t ti_buf[TI_BUFSZ];
     int sense;
@@ -62,6 +62,15 @@ struct ESPState {
     uint8_t cmdbuf[TI_BUFSZ];
     int cmdlen;
     int do_cmd;
+
+    /* The amount of data left in the current DMA transfer.  */
+    uint32_t dma_left;
+    /* The size of the current DMA transfer.  Zero if no transfer is in
+       progress.  */
+    uint32_t dma_counter;
+    uint8_t *async_buf;
+    uint32_t async_len;
+    void *dma_opaque;
 };
 
 #define STAT_DO 0x00
@@ -72,6 +81,8 @@ struct ESPState {
 #define STAT_MO 0x07
 
 #define STAT_TC 0x10
+#define STAT_PE 0x20
+#define STAT_GE 0x40
 #define STAT_IN 0x80
 
 #define INTR_FC 0x08
@@ -84,17 +95,14 @@ struct ESPState {
 
 static int get_cmd(ESPState *s, uint8_t *buf)
 {
-    uint32_t dmaptr, dmalen;
+    uint32_t dmalen;
     int target;
 
-    dmalen = s->wregs[0] | (s->wregs[1] << 8);
+    dmalen = s->rregs[0] | (s->rregs[1] << 8);
     target = s->wregs[4] & 7;
     DPRINTF("get_cmd: len %d target %d\n", dmalen, target);
     if (s->dma) {
-       dmaptr = iommu_translate(s->espdmaregs[1]);
-       DPRINTF("DMA Direction: %c, addr 0x%8.8x\n",
-                s->espdmaregs[0] & DMA_WRITE_MEM ? 'w': 'r', dmaptr);
-       cpu_physical_memory_read(dmaptr, buf, dmalen);
+        espdma_memory_read(s->dma_opaque, buf, dmalen);
     } else {
        buf[0] = 0;
        memcpy(&buf[1], s->ti_buf, dmalen);
@@ -105,13 +113,18 @@ static int get_cmd(ESPState *s, uint8_t *buf)
     s->ti_rptr = 0;
     s->ti_wptr = 0;
 
-    if (target >= 4 || !s->scsi_dev[target]) {
+    if (s->current_dev) {
+        /* Started a new command before the old one finished.  Cancel it.  */
+        scsi_cancel_io(s->current_dev, 0);
+        s->async_len = 0;
+    }
+
+    if (target >= MAX_DISKS || !s->scsi_dev[target]) {
         // No such drive
        s->rregs[4] = STAT_IN;
        s->rregs[5] = INTR_DC;
        s->rregs[6] = SEQ_0;
-       s->espdmaregs[0] |= DMA_INTR;
-       pic_set_irq(s->irq, 1);
+       espdma_raise_irq(s->dma_opaque);
        return 0;
     }
     s->current_dev = s->scsi_dev[target];
@@ -126,22 +139,22 @@ static void do_cmd(ESPState *s, uint8_t *buf)
     DPRINTF("do_cmd: busid 0x%x\n", buf[0]);
     lun = buf[0] & 7;
     datalen = scsi_send_command(s->current_dev, 0, &buf[1], lun);
-    if (datalen == 0) {
-        s->ti_size = 0;
-    } else {
+    s->ti_size = datalen;
+    if (datalen != 0) {
         s->rregs[4] = STAT_IN | STAT_TC;
+        s->dma_left = 0;
+        s->dma_counter = 0;
         if (datalen > 0) {
             s->rregs[4] |= STAT_DI;
-            s->ti_size = datalen;
+            scsi_read_data(s->current_dev, 0);
         } else {
             s->rregs[4] |= STAT_DO;
-            s->ti_size = -datalen;
+            scsi_write_data(s->current_dev, 0);
         }
     }
     s->rregs[5] = INTR_BS | INTR_FC;
     s->rregs[6] = SEQ_CD;
-    s->espdmaregs[0] |= DMA_INTR;
-    pic_set_irq(s->irq, 1);
+    espdma_raise_irq(s->dma_opaque);
 }
 
 static void handle_satn(ESPState *s)
@@ -160,27 +173,20 @@ static void handle_satn_stop(ESPState *s)
     if (s->cmdlen) {
         DPRINTF("Set ATN & Stop: cmdlen %d\n", s->cmdlen);
         s->do_cmd = 1;
-        s->espdmaregs[1] += s->cmdlen;
         s->rregs[4] = STAT_IN | STAT_TC | STAT_CD;
         s->rregs[5] = INTR_BS | INTR_FC;
         s->rregs[6] = SEQ_CD;
-        s->espdmaregs[0] |= DMA_INTR;
-        pic_set_irq(s->irq, 1);
+        espdma_raise_irq(s->dma_opaque);
     }
 }
 
 static void write_response(ESPState *s)
 {
-    uint32_t dmaptr;
-
     DPRINTF("Transfer status (sense=%d)\n", s->sense);
     s->ti_buf[0] = s->sense;
     s->ti_buf[1] = 0;
     if (s->dma) {
-       dmaptr = iommu_translate(s->espdmaregs[1]);
-       DPRINTF("DMA Direction: %c\n",
-                s->espdmaregs[0] & DMA_WRITE_MEM ? 'w': 'r');
-       cpu_physical_memory_write(dmaptr, s->ti_buf, 2);
+        espdma_memory_write(s->dma_opaque, s->ti_buf, 2);
        s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
        s->rregs[5] = INTR_BS | INTR_FC;
        s->rregs[6] = SEQ_CD;
@@ -190,84 +196,127 @@ static void write_response(ESPState *s)
        s->ti_wptr = 0;
        s->rregs[7] = 2;
     }
-    s->espdmaregs[0] |= DMA_INTR;
-    pic_set_irq(s->irq, 1);
+    espdma_raise_irq(s->dma_opaque);
+}
 
+static void esp_dma_done(ESPState *s)
+{
+    s->rregs[4] |= STAT_IN | STAT_TC;
+    s->rregs[5] = INTR_BS;
+    s->rregs[6] = 0;
+    s->rregs[7] = 0;
+    s->rregs[0] = 0;
+    s->rregs[1] = 0;
+    espdma_raise_irq(s->dma_opaque);
 }
 
-static void esp_command_complete(void *opaque, uint32_t tag, int sense)
+static void esp_do_dma(ESPState *s)
+{
+    uint32_t len;
+    int to_device;
+
+    to_device = (s->ti_size < 0);
+    len = s->dma_left;
+    if (s->do_cmd) {
+        DPRINTF("command len %d + %d\n", s->cmdlen, len);
+        espdma_memory_read(s->dma_opaque, &s->cmdbuf[s->cmdlen], len);
+        s->ti_size = 0;
+        s->cmdlen = 0;
+        s->do_cmd = 0;
+        do_cmd(s, s->cmdbuf);
+        return;
+    }
+    if (s->async_len == 0) {
+        /* Defer until data is available.  */
+        return;
+    }
+    if (len > s->async_len) {
+        len = s->async_len;
+    }
+    if (to_device) {
+        espdma_memory_read(s->dma_opaque, s->async_buf, len);
+    } else {
+        espdma_memory_write(s->dma_opaque, s->async_buf, len);
+    }
+    s->dma_left -= len;
+    s->async_buf += len;
+    s->async_len -= len;
+    if (to_device)
+        s->ti_size += len;
+    else
+        s->ti_size -= len;
+    if (s->async_len == 0) {
+        if (to_device) {
+            // ti_size is negative
+            scsi_write_data(s->current_dev, 0);
+        } else {
+            scsi_read_data(s->current_dev, 0);
+            /* If there is still data to be read from the device then
+               complete the DMA operation immeriately.  Otherwise defer
+               until the scsi layer has completed.  */
+            if (s->dma_left == 0 && s->ti_size > 0) {
+                esp_dma_done(s);
+            }
+        }
+    } else {
+        /* Partially filled a scsi buffer. Complete immediately.  */
+        esp_dma_done(s);
+    }
+}
+
+static void esp_command_complete(void *opaque, int reason, uint32_t tag,
+                                 uint32_t arg)
 {
     ESPState *s = (ESPState *)opaque;
 
-    DPRINTF("SCSI Command complete\n");
-    if (s->ti_size != 0)
-        DPRINTF("SCSI command completed unexpectedly\n");
-    s->ti_size = 0;
-    if (sense)
-        DPRINTF("Command failed\n");
-    s->sense = sense;
-    s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
+    if (reason == SCSI_REASON_DONE) {
+        DPRINTF("SCSI Command complete\n");
+        if (s->ti_size != 0)
+            DPRINTF("SCSI command completed unexpectedly\n");
+        s->ti_size = 0;
+        s->dma_left = 0;
+        s->async_len = 0;
+        if (arg)
+            DPRINTF("Command failed\n");
+        s->sense = arg;
+        s->rregs[4] = STAT_ST;
+        esp_dma_done(s);
+        s->current_dev = NULL;
+    } else {
+        DPRINTF("transfer %d/%d\n", s->dma_left, s->ti_size);
+        s->async_len = arg;
+        s->async_buf = scsi_get_buf(s->current_dev, 0);
+        if (s->dma_left) {
+            esp_do_dma(s);
+        } else if (s->dma_counter != 0 && s->ti_size <= 0) {
+            /* If this was the last part of a DMA transfer then the
+               completion interrupt is deferred to here.  */
+            esp_dma_done(s);
+        }
+    }
 }
 
 static void handle_ti(ESPState *s)
 {
-    uint32_t dmaptr, dmalen, minlen, len, from, to;
-    unsigned int i;
-    int to_device;
-    uint8_t buf[TARGET_PAGE_SIZE];
+    uint32_t dmalen, minlen;
 
-    dmalen = s->wregs[0] | (s->wregs[1] << 8);
+    dmalen = s->rregs[0] | (s->rregs[1] << 8);
     if (dmalen==0) {
       dmalen=0x10000;
     }
+    s->dma_counter = dmalen;
 
     if (s->do_cmd)
         minlen = (dmalen < 32) ? dmalen : 32;
+    else if (s->ti_size < 0)
+        minlen = (dmalen < -s->ti_size) ? dmalen : -s->ti_size;
     else
         minlen = (dmalen < s->ti_size) ? dmalen : s->ti_size;
     DPRINTF("Transfer Information len %d\n", minlen);
     if (s->dma) {
-       dmaptr = iommu_translate(s->espdmaregs[1]);
-        /* Check if the transfer writes to to reads from the device.  */
-        to_device = (s->espdmaregs[0] & DMA_WRITE_MEM) == 0;
-       DPRINTF("DMA Direction: %c, addr 0x%8.8x %08x\n",
-                to_device ? 'r': 'w', dmaptr, s->ti_size);
-       from = s->espdmaregs[1];
-       to = from + minlen;
-       for (i = 0; i < minlen; i += len, from += len) {
-           dmaptr = iommu_translate(s->espdmaregs[1] + i);
-           if ((from & TARGET_PAGE_MASK) != (to & TARGET_PAGE_MASK)) {
-               len = TARGET_PAGE_SIZE - (from & ~TARGET_PAGE_MASK);
-            } else {
-              len = to - from;
-            }
-            DPRINTF("DMA address p %08x v %08x len %08x, from %08x, to %08x\n", dmaptr, s->espdmaregs[1] + i, len, from, to);
-            s->ti_size -= len;
-            if (s->do_cmd) {
-                DPRINTF("command len %d + %d\n", s->cmdlen, len);
-                cpu_physical_memory_read(dmaptr, &s->cmdbuf[s->cmdlen], len);
-                s->ti_size = 0;
-                s->cmdlen = 0;
-                s->do_cmd = 0;
-                do_cmd(s, s->cmdbuf);
-                return;
-            } else {
-                if (to_device) {
-                    cpu_physical_memory_read(dmaptr, buf, len);
-                    scsi_write_data(s->current_dev, buf, len);
-                } else {
-                    scsi_read_data(s->current_dev, buf, len);
-                    cpu_physical_memory_write(dmaptr, buf, len);
-                }
-            }
-        }
-        if (s->ti_size) {
-           s->rregs[4] = STAT_IN | STAT_TC | (to_device ? STAT_DO : STAT_DI);
-        }
-        s->rregs[5] = INTR_BS;
-       s->rregs[6] = 0;
-       s->rregs[7] = 0;
-       s->espdmaregs[0] |= DMA_INTR;
+        s->dma_left = minlen;
+        s->rregs[4] &= ~STAT_TC;
+        esp_do_dma(s);
     } else if (s->do_cmd) {
         DPRINTF("command len %d\n", s->cmdlen);
         s->ti_size = 0;
@@ -276,16 +325,15 @@ static void handle_ti(ESPState *s)
         do_cmd(s, s->cmdbuf);
         return;
     }
-    pic_set_irq(s->irq, 1);
 }
 
-static void esp_reset(void *opaque)
+void esp_reset(void *opaque)
 {
     ESPState *s = opaque;
+
     memset(s->rregs, 0, ESP_MAXREG);
     memset(s->wregs, 0, ESP_MAXREG);
     s->rregs[0x0e] = 0x4; // Indicate fas100a
-    memset(s->espdmaregs, 0, ESPDMA_REGS * 4);
     s->ti_size = 0;
     s->ti_rptr = 0;
     s->ti_wptr = 0;
@@ -307,11 +355,12 @@ static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
            s->ti_size--;
             if ((s->rregs[4] & 6) == 0) {
                 /* Data in/out.  */
-                scsi_read_data(s->current_dev, &s->rregs[2], 0);
+                fprintf(stderr, "esp: PIO data read not implemented\n");
+                s->rregs[2] = 0;
             } else {
                 s->rregs[2] = s->ti_buf[s->ti_rptr++];
             }
-           pic_set_irq(s->irq, 1);
+            espdma_raise_irq(s->dma_opaque);
        }
        if (s->ti_size == 0) {
             s->ti_rptr = 0;
@@ -320,10 +369,9 @@ static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
        break;
     case 5:
         // interrupt
-        // Clear status bits except TC
-        s->rregs[4] &= STAT_TC;
-        pic_set_irq(s->irq, 0);
-       s->espdmaregs[0] &= ~DMA_INTR;
+        // Clear interrupt/error status bits
+        s->rregs[4] &= ~(STAT_IN | STAT_GE | STAT_PE);
+       espdma_clear_irq(s->dma_opaque);
         break;
     default:
        break;
@@ -341,7 +389,7 @@ static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
     switch (saddr) {
     case 0:
     case 1:
-        s->rregs[saddr] = val;
+        s->rregs[4] &= ~STAT_TC;
         break;
     case 2:
        // FIFO
@@ -351,7 +399,7 @@ static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
             uint8_t buf;
             buf = val & 0xff;
             s->ti_size--;
-            scsi_write_data(s->current_dev, &buf, 0);
+            fprintf(stderr, "esp: PIO data write not implemented\n");
         } else {
             s->ti_size++;
             s->ti_buf[s->ti_wptr++] = val & 0xff;
@@ -362,6 +410,9 @@ static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
        // Command
        if (val & 0x80) {
            s->dma = 1;
+            /* Reload DMA counter.  */
+            s->rregs[0] = s->wregs[0];
+            s->rregs[1] = s->wregs[1];
        } else {
            s->dma = 0;
        }
@@ -383,8 +434,7 @@ static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
            DPRINTF("Bus reset (%2.2x)\n", val);
            s->rregs[5] = INTR_RST;
             if (!(s->wregs[8] & 0x40)) {
-                s->espdmaregs[0] |= DMA_INTR;
-                pic_set_irq(s->irq, 1);
+                espdma_raise_irq(s->dma_opaque);
             }
            break;
        case 0x10:
@@ -447,68 +497,12 @@ static CPUWriteMemoryFunc *esp_mem_write[3] = {
     esp_mem_writeb,
 };
 
-static uint32_t espdma_mem_readl(void *opaque, target_phys_addr_t addr)
-{
-    ESPState *s = opaque;
-    uint32_t saddr;
-
-    saddr = (addr & ESPDMA_MAXADDR) >> 2;
-    DPRINTF("read dmareg[%d]: 0x%8.8x\n", saddr, s->espdmaregs[saddr]);
-
-    return s->espdmaregs[saddr];
-}
-
-static void espdma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-    ESPState *s = opaque;
-    uint32_t saddr;
-
-    saddr = (addr & ESPDMA_MAXADDR) >> 2;
-    DPRINTF("write dmareg[%d]: 0x%8.8x -> 0x%8.8x\n", saddr, s->espdmaregs[saddr], val);
-    switch (saddr) {
-    case 0:
-       if (!(val & DMA_INTREN))
-           pic_set_irq(s->irq, 0);
-       if (val & 0x80) {
-            esp_reset(s);
-        } else if (val & 0x40) {
-            val &= ~0x40;
-        } else if (val == 0)
-            val = 0x40;
-        val &= 0x0fffffff;
-        val |= DMA_VER;
-       break;
-    case 1:
-        s->espdmaregs[0] |= DMA_LOADED;
-        break;
-    default:
-       break;
-    }
-    s->espdmaregs[saddr] = val;
-}
-
-static CPUReadMemoryFunc *espdma_mem_read[3] = {
-    espdma_mem_readl,
-    espdma_mem_readl,
-    espdma_mem_readl,
-};
-
-static CPUWriteMemoryFunc *espdma_mem_write[3] = {
-    espdma_mem_writel,
-    espdma_mem_writel,
-    espdma_mem_writel,
-};
-
 static void esp_save(QEMUFile *f, void *opaque)
 {
     ESPState *s = opaque;
-    unsigned int i;
 
     qemu_put_buffer(f, s->rregs, ESP_MAXREG);
     qemu_put_buffer(f, s->wregs, ESP_MAXREG);
-    qemu_put_be32s(f, &s->irq);
-    for (i = 0; i < ESPDMA_REGS; i++)
-       qemu_put_be32s(f, &s->espdmaregs[i]);
     qemu_put_be32s(f, &s->ti_size);
     qemu_put_be32s(f, &s->ti_rptr);
     qemu_put_be32s(f, &s->ti_wptr);
@@ -519,16 +513,12 @@ static void esp_save(QEMUFile *f, void *opaque)
 static int esp_load(QEMUFile *f, void *opaque, int version_id)
 {
     ESPState *s = opaque;
-    unsigned int i;
     
-    if (version_id != 1)
-        return -EINVAL;
+    if (version_id != 2)
+        return -EINVAL; // Cannot emulate 1
 
     qemu_get_buffer(f, s->rregs, ESP_MAXREG);
     qemu_get_buffer(f, s->wregs, ESP_MAXREG);
-    qemu_get_be32s(f, &s->irq);
-    for (i = 0; i < ESPDMA_REGS; i++)
-       qemu_get_be32s(f, &s->espdmaregs[i]);
     qemu_get_be32s(f, &s->ti_size);
     qemu_get_be32s(f, &s->ti_rptr);
     qemu_get_be32s(f, &s->ti_wptr);
@@ -538,34 +528,48 @@ static int esp_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-void esp_init(BlockDriverState **bd, int irq, uint32_t espaddr, uint32_t espdaddr)
+void esp_scsi_attach(void *opaque, BlockDriverState *bd, int id)
+{
+    ESPState *s = (ESPState *)opaque;
+
+    if (id < 0) {
+        for (id = 0; id < ESP_MAX_DEVS; id++) {
+            if (s->scsi_dev[id] == NULL)
+                break;
+        }
+    }
+    if (id >= ESP_MAX_DEVS) {
+        DPRINTF("Bad Device ID %d\n", id);
+        return;
+    }
+    if (s->scsi_dev[id]) {
+        DPRINTF("Destroying device %d\n", id);
+        scsi_disk_destroy(s->scsi_dev[id]);
+    }
+    DPRINTF("Attaching block device %d\n", id);
+    /* Command queueing is not implemented.  */
+    s->scsi_dev[id] = scsi_disk_init(bd, 0, esp_command_complete, s);
+}
+
+void *esp_init(BlockDriverState **bd, uint32_t espaddr, void *dma_opaque)
 {
     ESPState *s;
-    int esp_io_memory, espdma_io_memory;
-    int i;
+    int esp_io_memory;
 
     s = qemu_mallocz(sizeof(ESPState));
     if (!s)
-        return;
+        return NULL;
 
     s->bd = bd;
-    s->irq = irq;
+    s->dma_opaque = dma_opaque;
 
     esp_io_memory = cpu_register_io_memory(0, esp_mem_read, esp_mem_write, s);
     cpu_register_physical_memory(espaddr, ESP_MAXREG*4, esp_io_memory);
 
-    espdma_io_memory = cpu_register_io_memory(0, espdma_mem_read, espdma_mem_write, s);
-    cpu_register_physical_memory(espdaddr, 16, espdma_io_memory);
-
     esp_reset(s);
 
-    register_savevm("esp", espaddr, 1, esp_save, esp_load, s);
+    register_savevm("esp", espaddr, 2, esp_save, esp_load, s);
     qemu_register_reset(esp_reset, s);
-    for (i = 0; i < MAX_DISKS; i++) {
-        if (bs_table[i]) {
-            s->scsi_dev[i] =
-                scsi_disk_init(bs_table[i], esp_command_complete, s);
-        }
-    }
-}
 
+    return s;
+}
index 1d16cd6518cd7c45bacb9c3d0f16fc6f61681ee7..0012834f44e49d7d6c6770571dc48d8b182fd09c 100644 (file)
@@ -66,7 +66,6 @@ typedef enum fdrive_type_t {
 
 typedef enum fdrive_flags_t {
     FDRIVE_MOTOR_ON   = 0x01, /* motor on/off           */
-    FDRIVE_REVALIDATE = 0x02, /* Revalidated            */
 } fdrive_flags_t;
 
 typedef enum fdisk_flags_t {
@@ -236,7 +235,6 @@ static void fd_revalidate (fdrive_t *drv)
     int nb_heads, max_track, last_sect, ro;
 
     FLOPPY_DPRINTF("revalidate\n");
-    drv->drflags &= ~FDRIVE_REVALIDATE;
     if (drv->bs != NULL && bdrv_is_inserted(drv->bs)) {
        ro = bdrv_is_read_only(drv->bs);
        bdrv_get_geometry_hint(drv->bs, &nb_heads, &max_track, &last_sect);
@@ -291,7 +289,6 @@ static void fd_revalidate (fdrive_t *drv)
        drv->max_track = 0;
        drv->flags &= ~FDISK_DBL_SIDES;
     }
-    drv->drflags |= FDRIVE_REVALIDATE;
 }
 
 /* Motor control */
@@ -488,19 +485,6 @@ static CPUWriteMemoryFunc *fdctrl_mem_write[3] = {
     fdctrl_write_mem,
 };
 
-static void fd_change_cb (void *opaque)
-{
-    fdrive_t *drv = opaque;
-
-    FLOPPY_DPRINTF("disk change\n");
-    fd_revalidate(drv);
-#if 0
-    fd_recalibrate(drv);
-    fdctrl_reset_fifo(drv->fdctrl);
-    fdctrl_raise_irq(drv->fdctrl, 0x20);
-#endif
-}
-
 fdctrl_t *fdctrl_init (int irq_lvl, int dma_chann, int mem_mapped, 
                        uint32_t io_base,
                        BlockDriverState **fds)
@@ -529,10 +513,6 @@ fdctrl_t *fdctrl_init (int irq_lvl, int dma_chann, int mem_mapped,
     }
     for (i = 0; i < 2; i++) {
         fd_init(&fdctrl->drives[i], fds[i]);
-        if (fds[i]) {
-            bdrv_set_change_cb(fds[i],
-                               &fd_change_cb, &fdctrl->drives[i]);
-        }
     }
     fdctrl_reset(fdctrl, 0);
     fdctrl->state = FD_CTRL_ACTIVE;
@@ -760,18 +740,28 @@ static void fdctrl_write_rate (fdctrl_t *fdctrl, uint32_t value)
 //        fdctrl.precomp = (value >> 2) & 0x07;
 }
 
+static int fdctrl_media_changed(fdrive_t *drv)
+{
+    int ret;
+    if (!drv->bs) 
+        return 0;
+    ret = bdrv_media_changed(drv->bs);
+    if (ret) {
+        fd_revalidate(drv);
+    }
+    return ret;
+}
+
 /* Digital input register : 0x07 (read-only) */
 static uint32_t fdctrl_read_dir (fdctrl_t *fdctrl)
 {
     uint32_t retval = 0;
 
-    if (drv0(fdctrl)->drflags & FDRIVE_REVALIDATE ||
-       drv1(fdctrl)->drflags & FDRIVE_REVALIDATE)
+    if (fdctrl_media_changed(drv0(fdctrl)) ||
+       fdctrl_media_changed(drv1(fdctrl)))
         retval |= 0x80;
     if (retval != 0)
         FLOPPY_DPRINTF("Floppy digital input register: 0x%02x\n", retval);
-    drv0(fdctrl)->drflags &= ~FDRIVE_REVALIDATE;
-    drv1(fdctrl)->drflags &= ~FDRIVE_REVALIDATE;
 
     return retval;
 }
@@ -1683,8 +1673,9 @@ enqueue:
 #else
            cur_drv->last_sect = fdctrl->fifo[3];
 #endif
-           /* Bochs BIOS is buggy and don't send format informations
-            * for each sector. So, pretend all's done right now...
+           /* TODO: implement format using DMA expected by the Bochs BIOS
+            * and Linux fdformat (read 3 bytes per sector via DMA and fill
+            * the sector with the specified fill byte
             */
            fdctrl->data_state &= ~FD_STATE_FORMAT;
            fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
index e3cbceb49ab5eb3e04de2ed584fb168eec1dc35b..4004f9942fdb54b1842b42a72525783ed4d28b12 100644 (file)
@@ -74,11 +74,15 @@ static CPUReadMemoryFunc *pci_grackle_read[] = {
     &pci_host_data_readl,
 };
 
-/* XXX: we do not simulate the hardware - we rely on the BIOS to
-   set correctly for irq line field */
-static void pci_grackle_set_irq(PCIDevice *d, void *pic, int irq_num, int level)
+/* Don't know if this matches real hardware, but it agrees with OHW.  */
+static int pci_grackle_map_irq(PCIDevice *pci_dev, int irq_num)
 {
-    heathrow_pic_set_irq(pic, d->config[PCI_INTERRUPT_LINE], level);
+    return (irq_num + (pci_dev->devfn >> 3)) & 3;
+}
+
+static void pci_grackle_set_irq(void *pic, int irq_num, int level)
+{
+    heathrow_pic_set_irq(pic, irq_num + 8, level);
 }
 
 PCIBus *pci_grackle_init(uint32_t base, void *pic)
@@ -88,7 +92,8 @@ PCIBus *pci_grackle_init(uint32_t base, void *pic)
     int pci_mem_config, pci_mem_data;
 
     s = qemu_mallocz(sizeof(GrackleState));
-    s->bus = pci_register_bus(pci_grackle_set_irq, pic, 0);
+    s->bus = pci_register_bus(pci_grackle_set_irq, pci_grackle_map_irq,
+                              pic, 0, 0);
 
     pci_mem_config = cpu_register_io_memory(0, pci_grackle_config_read, 
                                             pci_grackle_config_write, s);
diff --git a/tools/ioemu/hw/gt64xxx.c b/tools/ioemu/hw/gt64xxx.c
new file mode 100644 (file)
index 0000000..ccb6a7c
--- /dev/null
@@ -0,0 +1,648 @@
+/*
+ * QEMU GT64120 PCI host
+ *
+ * Copyright (c) 2006,2007 Aurelien Jarno
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "vl.h"
+typedef target_phys_addr_t pci_addr_t;
+#include "pci_host.h"
+
+#define GT_REGS                        (0x1000 >> 2)
+
+/* CPU Configuration */
+#define GT_CPU                 (0x000 >> 2)
+#define GT_MULTI               (0x120 >> 2)
+
+/* CPU Address Decode */
+#define GT_SCS10LD             (0x008 >> 2)
+#define GT_SCS10HD             (0x010 >> 2)
+#define GT_SCS32LD             (0x018 >> 2)
+#define GT_SCS32HD             (0x020 >> 2)
+#define GT_CS20LD              (0x028 >> 2)
+#define GT_CS20HD              (0x030 >> 2)
+#define GT_CS3BOOTLD           (0x038 >> 2)
+#define GT_CS3BOOTHD           (0x040 >> 2)
+#define GT_PCI0IOLD                    (0x048 >> 2)
+#define GT_PCI0IOHD                    (0x050 >> 2)
+#define GT_PCI0M0LD                    (0x058 >> 2)
+#define GT_PCI0M0HD                    (0x060 >> 2)
+#define GT_ISD                 (0x068 >> 2)
+
+#define GT_PCI0M1LD                    (0x080 >> 2)
+#define GT_PCI0M1HD                    (0x088 >> 2)
+#define GT_PCI1IOLD                    (0x090 >> 2)
+#define GT_PCI1IOHD                    (0x098 >> 2)
+#define GT_PCI1M0LD                    (0x0a0 >> 2)
+#define GT_PCI1M0HD                    (0x0a8 >> 2)
+#define GT_PCI1M1LD                    (0x0b0 >> 2)
+#define GT_PCI1M1HD                    (0x0b8 >> 2)
+#define GT_PCI1M1LD                    (0x0b0 >> 2)
+#define GT_PCI1M1HD                    (0x0b8 >> 2)
+
+#define GT_SCS10AR             (0x0d0 >> 2)
+#define GT_SCS32AR             (0x0d8 >> 2)
+#define GT_CS20R               (0x0e0 >> 2)
+#define GT_CS3BOOTR                    (0x0e8 >> 2)
+
+#define GT_PCI0IOREMAP         (0x0f0 >> 2)
+#define GT_PCI0M0REMAP         (0x0f8 >> 2)
+#define GT_PCI0M1REMAP         (0x100 >> 2)
+#define GT_PCI1IOREMAP         (0x108 >> 2)
+#define GT_PCI1M0REMAP         (0x110 >> 2)
+#define GT_PCI1M1REMAP         (0x118 >> 2)
+
+/* CPU Error Report */
+#define GT_CPUERR_ADDRLO       (0x070 >> 2)
+#define GT_CPUERR_ADDRHI       (0x078 >> 2)
+#define GT_CPUERR_DATALO       (0x128 >> 2)            /* GT-64120A only  */
+#define GT_CPUERR_DATAHI       (0x130 >> 2)            /* GT-64120A only  */
+#define GT_CPUERR_PARITY       (0x138 >> 2)            /* GT-64120A only  */
+
+/* CPU Sync Barrier */
+#define GT_PCI0SYNC                    (0x0c0 >> 2)
+#define GT_PCI1SYNC                    (0x0c8 >> 2)
+
+/* SDRAM and Device Address Decode */
+#define GT_SCS0LD              (0x400 >> 2)
+#define GT_SCS0HD              (0x404 >> 2)
+#define GT_SCS1LD              (0x408 >> 2)
+#define GT_SCS1HD              (0x40c >> 2)
+#define GT_SCS2LD              (0x410 >> 2)
+#define GT_SCS2HD              (0x414 >> 2)
+#define GT_SCS3LD              (0x418 >> 2)
+#define GT_SCS3HD              (0x41c >> 2)
+#define GT_CS0LD               (0x420 >> 2)
+#define GT_CS0HD               (0x424 >> 2)
+#define GT_CS1LD               (0x428 >> 2)
+#define GT_CS1HD               (0x42c >> 2)
+#define GT_CS2LD               (0x430 >> 2)
+#define GT_CS2HD               (0x434 >> 2)
+#define GT_CS3LD               (0x438 >> 2)
+#define GT_CS3HD               (0x43c >> 2)
+#define GT_BOOTLD              (0x440 >> 2)
+#define GT_BOOTHD              (0x444 >> 2)
+#define GT_ADERR               (0x470 >> 2)
+
+/* SDRAM Configuration */
+#define GT_SDRAM_CFG           (0x448 >> 2)
+#define GT_SDRAM_OPMODE        (0x474 >> 2)
+#define GT_SDRAM_BM                    (0x478 >> 2)
+#define GT_SDRAM_ADDRDECODE            (0x47c >> 2)
+
+/* SDRAM Parameters */
+#define GT_SDRAM_B0                    (0x44c >> 2)
+#define GT_SDRAM_B1                    (0x450 >> 2)
+#define GT_SDRAM_B2                    (0x454 >> 2)
+#define GT_SDRAM_B3                    (0x458 >> 2)
+
+/* Device Parameters */
+#define GT_DEV_B0              (0x45c >> 2)
+#define GT_DEV_B1              (0x460 >> 2)
+#define GT_DEV_B2              (0x464 >> 2)
+#define GT_DEV_B3              (0x468 >> 2)
+#define GT_DEV_BOOT                    (0x46c >> 2)
+
+/* ECC */
+#define GT_ECC_ERRDATALO       (0x480 >> 2)            /* GT-64120A only  */
+#define GT_ECC_ERRDATAHI       (0x484 >> 2)            /* GT-64120A only  */
+#define GT_ECC_MEM             (0x488 >> 2)            /* GT-64120A only  */
+#define GT_ECC_CALC            (0x48c >> 2)            /* GT-64120A only  */
+#define GT_ECC_ERRADDR         (0x490 >> 2)            /* GT-64120A only  */
+
+/* DMA Record */
+#define GT_DMA0_CNT                    (0x800 >> 2)
+#define GT_DMA1_CNT                    (0x804 >> 2)
+#define GT_DMA2_CNT                    (0x808 >> 2)
+#define GT_DMA3_CNT                    (0x80c >> 2)
+#define GT_DMA0_SA             (0x810 >> 2)
+#define GT_DMA1_SA             (0x814 >> 2)
+#define GT_DMA2_SA             (0x818 >> 2)
+#define GT_DMA3_SA             (0x81c >> 2)
+#define GT_DMA0_DA             (0x820 >> 2)
+#define GT_DMA1_DA             (0x824 >> 2)
+#define GT_DMA2_DA             (0x828 >> 2)
+#define GT_DMA3_DA             (0x82c >> 2)
+#define GT_DMA0_NEXT           (0x830 >> 2)
+#define GT_DMA1_NEXT           (0x834 >> 2)
+#define GT_DMA2_NEXT           (0x838 >> 2)
+#define GT_DMA3_NEXT           (0x83c >> 2)
+#define GT_DMA0_CUR                    (0x870 >> 2)
+#define GT_DMA1_CUR                    (0x874 >> 2)
+#define GT_DMA2_CUR                    (0x878 >> 2)
+#define GT_DMA3_CUR                    (0x87c >> 2)
+
+/* DMA Channel Control */
+#define GT_DMA0_CTRL           (0x840 >> 2)
+#define GT_DMA1_CTRL           (0x844 >> 2)
+#define GT_DMA2_CTRL           (0x848 >> 2)
+#define GT_DMA3_CTRL           (0x84c >> 2)
+
+/* DMA Arbiter */
+#define GT_DMA_ARB             (0x860 >> 2)
+
+/* Timer/Counter */
+#define GT_TC0                 (0x850 >> 2)
+#define GT_TC1                 (0x854 >> 2)
+#define GT_TC2                 (0x858 >> 2)
+#define GT_TC3                 (0x85c >> 2)
+#define GT_TC_CONTROL          (0x864 >> 2)
+
+/* PCI Internal */
+#define GT_PCI0_CMD                    (0xc00 >> 2)
+#define GT_PCI0_TOR                    (0xc04 >> 2)
+#define GT_PCI0_BS_SCS10       (0xc08 >> 2)
+#define GT_PCI0_BS_SCS32       (0xc0c >> 2)
+#define GT_PCI0_BS_CS20        (0xc10 >> 2)
+#define GT_PCI0_BS_CS3BT       (0xc14 >> 2)
+#define GT_PCI1_IACK           (0xc30 >> 2)
+#define GT_PCI0_IACK           (0xc34 >> 2)
+#define GT_PCI0_BARE           (0xc3c >> 2)
+#define GT_PCI0_PREFMBR        (0xc40 >> 2)
+#define GT_PCI0_SCS10_BAR      (0xc48 >> 2)
+#define GT_PCI0_SCS32_BAR      (0xc4c >> 2)
+#define GT_PCI0_CS20_BAR       (0xc50 >> 2)
+#define GT_PCI0_CS3BT_BAR      (0xc54 >> 2)
+#define GT_PCI0_SSCS10_BAR     (0xc58 >> 2)
+#define GT_PCI0_SSCS32_BAR     (0xc5c >> 2)
+#define GT_PCI0_SCS3BT_BAR     (0xc64 >> 2)
+#define GT_PCI1_CMD                    (0xc80 >> 2)
+#define GT_PCI1_TOR                    (0xc84 >> 2)
+#define GT_PCI1_BS_SCS10       (0xc88 >> 2)
+#define GT_PCI1_BS_SCS32       (0xc8c >> 2)
+#define GT_PCI1_BS_CS20        (0xc90 >> 2)
+#define GT_PCI1_BS_CS3BT       (0xc94 >> 2)
+#define GT_PCI1_BARE           (0xcbc >> 2)
+#define GT_PCI1_PREFMBR        (0xcc0 >> 2)
+#define GT_PCI1_SCS10_BAR      (0xcc8 >> 2)
+#define GT_PCI1_SCS32_BAR      (0xccc >> 2)
+#define GT_PCI1_CS20_BAR       (0xcd0 >> 2)
+#define GT_PCI1_CS3BT_BAR      (0xcd4 >> 2)
+#define GT_PCI1_SSCS10_BAR     (0xcd8 >> 2)
+#define GT_PCI1_SSCS32_BAR     (0xcdc >> 2)
+#define GT_PCI1_SCS3BT_BAR     (0xce4 >> 2)
+#define GT_PCI1_CFGADDR        (0xcf0 >> 2)
+#define GT_PCI1_CFGDATA        (0xcf4 >> 2)
+#define GT_PCI0_CFGADDR        (0xcf8 >> 2)
+#define GT_PCI0_CFGDATA        (0xcfc >> 2)
+
+/* Interrupts */
+#define GT_INTRCAUSE           (0xc18 >> 2)
+#define GT_INTRMASK                    (0xc1c >> 2)
+#define GT_PCI0_ICMASK         (0xc24 >> 2)
+#define GT_PCI0_SERR0MASK      (0xc28 >> 2)
+#define GT_CPU_INTSEL          (0xc70 >> 2)
+#define GT_PCI0_INTSEL         (0xc74 >> 2)
+#define GT_HINTRCAUSE          (0xc98 >> 2)
+#define GT_HINTRMASK           (0xc9c >> 2)
+#define GT_PCI0_HICMASK        (0xca4 >> 2)
+#define GT_PCI1_SERR1MASK      (0xca8 >> 2)
+
+
+typedef PCIHostState GT64120PCIState;
+
+typedef struct GT64120State {
+    GT64120PCIState *pci;
+    uint32_t regs[GT_REGS];
+} GT64120State;
+
+static void gt64120_pci_mapping(GT64120State *s)
+{
+    target_phys_addr_t start, length;             
+
+    /* Update IO mapping */
+    if ((s->regs[GT_PCI0IOLD] & 0x7f) <= s->regs[GT_PCI0IOHD])
+    {
+      start = s->regs[GT_PCI0IOLD] << 21;
+      length = ((s->regs[GT_PCI0IOHD] + 1) - (s->regs[GT_PCI0IOLD] & 0x7f)) << 21;
+      isa_mmio_init(start, length);
+    }
+}
+
+static void gt64120_writel (void *opaque, target_phys_addr_t addr,
+                            uint32_t val)
+{
+    GT64120State *s = opaque;
+    uint32_t saddr;
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    val = bswap32(val);
+#endif
+
+    saddr = (addr & 0xfff) >> 2;
+    switch (saddr) {
+
+    /* CPU Configuration */
+    case GT_CPU:
+        s->regs[GT_CPU] = val;
+        break;
+    case GT_MULTI:
+       /* Read-only register as only one GT64xxx is present on the CPU bus */
+        break;
+
+    /* CPU Address Decode */
+    case GT_PCI0IOLD:
+        s->regs[GT_PCI0IOLD]    = val & 0x00007fff;
+        s->regs[GT_PCI0IOREMAP] = val & 0x000007ff;
+        gt64120_pci_mapping(s);
+        break;
+    case GT_PCI0M0LD:
+        s->regs[GT_PCI0M0LD]    = val & 0x00007fff;
+        s->regs[GT_PCI0M0REMAP] = val & 0x000007ff;
+        gt64120_pci_mapping(s);
+        break;
+    case GT_PCI0M1LD:
+        s->regs[GT_PCI0M1LD]    = val & 0x00007fff;
+        s->regs[GT_PCI0M1REMAP] = val & 0x000007ff;
+        gt64120_pci_mapping(s);
+        break;
+    case GT_PCI1IOLD:
+        s->regs[GT_PCI1IOLD]    = val & 0x00007fff;
+        s->regs[GT_PCI1IOREMAP] = val & 0x000007ff;
+        gt64120_pci_mapping(s);
+        break;
+    case GT_PCI1M0LD:
+        s->regs[GT_PCI1M0LD]    = val & 0x00007fff;
+        s->regs[GT_PCI1M0REMAP] = val & 0x000007ff;
+        gt64120_pci_mapping(s);
+        break;
+    case GT_PCI1M1LD:
+        s->regs[GT_PCI1M1LD]    = val & 0x00007fff;
+        s->regs[GT_PCI1M1REMAP] = val & 0x000007ff;
+        gt64120_pci_mapping(s);
+        break;
+    case GT_PCI0IOHD:
+    case GT_PCI0M0HD:
+    case GT_PCI0M1HD:
+    case GT_PCI1IOHD:
+    case GT_PCI1M0HD:
+    case GT_PCI1M1HD:
+        s->regs[saddr] = val & 0x0000007f;
+        gt64120_pci_mapping(s);
+        break;
+    case GT_PCI0IOREMAP:
+    case GT_PCI0M0REMAP:
+    case GT_PCI0M1REMAP:
+    case GT_PCI1IOREMAP:
+    case GT_PCI1M0REMAP:
+    case GT_PCI1M1REMAP:
+        s->regs[saddr] = val & 0x000007ff;
+        gt64120_pci_mapping(s);
+        break;
+
+    /* CPU Error Report */
+    case GT_CPUERR_ADDRLO:
+    case GT_CPUERR_ADDRHI:
+    case GT_CPUERR_DATALO:
+    case GT_CPUERR_DATAHI:
+    case GT_CPUERR_PARITY:
+       /* Read-only registers, do nothing */
+        break;
+
+    /* CPU Sync Barrier */
+    case GT_PCI0SYNC:
+    case GT_PCI1SYNC:
+       /* Read-only registers, do nothing */
+        break;
+
+    /* ECC */
+    case GT_ECC_ERRDATALO:
+    case GT_ECC_ERRDATAHI:
+    case GT_ECC_MEM:
+    case GT_ECC_CALC:
+    case GT_ECC_ERRADDR:
+        /* Read-only registers, do nothing */
+        break;
+
+    /* PCI Internal */
+    case GT_PCI0_CMD:
+    case GT_PCI1_CMD:
+        s->regs[saddr] = val & 0x0401fc0f;
+        break;
+    case GT_PCI0_CFGADDR:
+        s->pci->config_reg = val & 0x80fffffc;
+        break;
+    case GT_PCI0_CFGDATA:
+        pci_host_data_writel(s->pci, 0, val);
+        break;
+
+    /* SDRAM Parameters */
+    case GT_SDRAM_B0:
+    case GT_SDRAM_B1:
+    case GT_SDRAM_B2:
+    case GT_SDRAM_B3:
+        /* We don't simulate electrical parameters of the SDRAM.
+           Accept, but ignore the values. */
+        s->regs[saddr] = val;
+        break;
+
+    default:
+#if 0
+        printf ("gt64120_writel: Bad register offset 0x%x\n", (int)addr);
+#endif
+        break;
+    }
+}
+
+static uint32_t gt64120_readl (void *opaque,
+                               target_phys_addr_t addr)
+{
+    GT64120State *s = opaque;
+    uint32_t val;
+    uint32_t saddr;
+
+    val = 0;
+    saddr = (addr & 0xfff) >> 2;
+
+    switch (saddr) {
+
+    /* CPU Configuration */
+    case GT_MULTI:
+        /* Only one GT64xxx is present on the CPU bus, return
+           the initial value */
+        val = s->regs[saddr];
+        break;
+
+    /* CPU Error Report */
+    case GT_CPUERR_ADDRLO:
+    case GT_CPUERR_ADDRHI:
+    case GT_CPUERR_DATALO:
+    case GT_CPUERR_DATAHI:
+    case GT_CPUERR_PARITY:
+        /* Emulated memory has no error, always return the initial
+           values */ 
+        val = s->regs[saddr];
+        break;
+
+    /* CPU Sync Barrier */
+    case GT_PCI0SYNC:
+    case GT_PCI1SYNC:
+        /* Reading those register should empty all FIFO on the PCI
+           bus, which are not emulated. The return value should be
+           a random value that should be ignored. */
+        val = 0xc000ffee; 
+        break;
+
+    /* ECC */
+    case GT_ECC_ERRDATALO:
+    case GT_ECC_ERRDATAHI:
+    case GT_ECC_MEM:
+    case GT_ECC_CALC:
+    case GT_ECC_ERRADDR:
+        /* Emulated memory has no error, always return the initial
+           values */ 
+        val = s->regs[saddr];
+        break;
+
+    case GT_CPU:
+    case GT_PCI0IOLD:
+    case GT_PCI0M0LD:
+    case GT_PCI0M1LD:
+    case GT_PCI1IOLD:
+    case GT_PCI1M0LD:
+    case GT_PCI1M1LD:
+    case GT_PCI0IOHD:
+    case GT_PCI0M0HD:
+    case GT_PCI0M1HD:
+    case GT_PCI1IOHD:
+    case GT_PCI1M0HD:
+    case GT_PCI1M1HD:
+    case GT_PCI0_CMD:
+    case GT_PCI1_CMD:
+    case GT_PCI0IOREMAP:
+    case GT_PCI0M0REMAP:
+    case GT_PCI0M1REMAP:
+    case GT_PCI1IOREMAP:
+    case GT_PCI1M0REMAP:
+    case GT_PCI1M1REMAP:
+        val = s->regs[saddr];
+        break;
+    case GT_PCI0_IACK:
+        /* Read the IRQ number */ 
+        val = pic_read_irq(isa_pic);
+        break;
+
+    /* SDRAM Parameters */
+    case GT_SDRAM_B0:
+    case GT_SDRAM_B1:
+    case GT_SDRAM_B2:
+    case GT_SDRAM_B3:
+        /* We don't simulate electrical parameters of the SDRAM.
+           Just return the last written value. */
+        val = s->regs[saddr];
+        break;
+
+    /* PCI Internal */
+    case GT_PCI0_CFGADDR:
+        val = s->pci->config_reg;
+        break;
+    case GT_PCI0_CFGDATA:
+        val = pci_host_data_readl(s->pci, 0);
+        break;
+
+    default:
+        val = s->regs[saddr];
+#if 0
+        printf ("gt64120_readl: Bad register offset 0x%x\n", (int)addr);
+#endif
+        break;
+    }
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    return bswap32(val);
+#else
+    return val;
+#endif
+}
+
+static CPUWriteMemoryFunc *gt64120_write[] = {
+    &gt64120_writel,
+    &gt64120_writel,
+    &gt64120_writel,
+};
+
+static CPUReadMemoryFunc *gt64120_read[] = {
+    &gt64120_readl,
+    &gt64120_readl,
+    &gt64120_readl,
+};
+
+static int pci_gt64120_map_irq(PCIDevice *pci_dev, int irq_num)
+{
+    int slot;
+
+    slot = (pci_dev->devfn >> 3);
+
+    switch (slot) {
+      /* PIIX4 USB */
+      case 10:
+        return 3;
+      /* AMD 79C973 Ethernet */
+      case 11:
+        return 0;
+      /* Crystal 4281 Sound */
+      case 12:
+        return 0;
+      /* PCI slot 1 to 4 */
+      case 18 ... 21:
+        return ((slot - 18) + irq_num) & 0x03;
+      /* Unknown device, don't do any translation */
+      default:
+        return irq_num;
+    }
+}
+
+extern PCIDevice *piix4_dev;
+static int pci_irq_levels[4];
+
+static void pci_gt64120_set_irq(void *pic, int irq_num, int level)
+{
+    int i, pic_irq, pic_level;
+
+    pci_irq_levels[irq_num] = level;
+
+    /* now we change the pic irq level according to the piix irq mappings */
+    /* XXX: optimize */
+    pic_irq = piix4_dev->config[0x60 + irq_num];
+    if (pic_irq < 16) {
+        /* The pic level is the logical OR of all the PCI irqs mapped
+           to it */
+        pic_level = 0;
+        for (i = 0; i < 4; i++) {
+            if (pic_irq == piix4_dev->config[0x60 + i])
+                pic_level |= pci_irq_levels[i];
+        }
+        pic_set_irq(pic_irq, pic_level);
+    }
+}
+
+
+void gt64120_reset(void *opaque)
+{
+    GT64120State *s = opaque;
+
+    /* CPU Configuration */
+#ifdef TARGET_WORDS_BIGENDIAN
+    s->regs[GT_CPU]           = 0x00000000;
+#else
+    s->regs[GT_CPU]           = 0x00000800;
+#endif
+    s->regs[GT_MULTI]         = 0x00000000;
+
+    /* CPU Address decode FIXME: not complete*/
+    s->regs[GT_PCI0IOLD]      = 0x00000080;
+    s->regs[GT_PCI0IOHD]      = 0x0000000f;
+    s->regs[GT_PCI0M0LD]      = 0x00000090;
+    s->regs[GT_PCI0M0HD]      = 0x0000001f;
+    s->regs[GT_PCI0M1LD]      = 0x00000790;
+    s->regs[GT_PCI0M1HD]      = 0x0000001f;
+    s->regs[GT_PCI1IOLD]      = 0x00000100;
+    s->regs[GT_PCI1IOHD]      = 0x0000000f;
+    s->regs[GT_PCI1M0LD]      = 0x00000110;
+    s->regs[GT_PCI1M0HD]      = 0x0000001f;
+    s->regs[GT_PCI1M1LD]      = 0x00000120;
+    s->regs[GT_PCI1M1HD]      = 0x0000002f;
+    s->regs[GT_PCI0IOREMAP]   = 0x00000080;
+    s->regs[GT_PCI0M0REMAP]   = 0x00000090;
+    s->regs[GT_PCI0M1REMAP]   = 0x00000790;
+    s->regs[GT_PCI1IOREMAP]   = 0x00000100;
+    s->regs[GT_PCI1M0REMAP]   = 0x00000110;
+    s->regs[GT_PCI1M1REMAP]   = 0x00000120;
+
+    /* CPU Error Report */
+    s->regs[GT_CPUERR_ADDRLO] = 0x00000000;
+    s->regs[GT_CPUERR_ADDRHI] = 0x00000000;
+    s->regs[GT_CPUERR_DATALO] = 0xffffffff;
+    s->regs[GT_CPUERR_DATAHI] = 0xffffffff;
+    s->regs[GT_CPUERR_PARITY] = 0x000000ff;
+
+    /* ECC */
+    s->regs[GT_ECC_ERRDATALO] = 0x00000000;
+    s->regs[GT_ECC_ERRDATAHI] = 0x00000000;
+    s->regs[GT_ECC_MEM]       = 0x00000000;
+    s->regs[GT_ECC_CALC]      = 0x00000000;
+    s->regs[GT_ECC_ERRADDR]   = 0x00000000;
+
+    /* SDRAM Parameters */
+    s->regs[GT_SDRAM_B0]      = 0x00000005;    
+    s->regs[GT_SDRAM_B1]      = 0x00000005;    
+    s->regs[GT_SDRAM_B2]      = 0x00000005;    
+    s->regs[GT_SDRAM_B3]      = 0x00000005;    
+
+    /* PCI Internal FIXME: not complete*/
+#ifdef TARGET_WORDS_BIGENDIAN
+    s->regs[GT_PCI0_CMD]      = 0x00000000;
+    s->regs[GT_PCI1_CMD]      = 0x00000000;
+#else
+    s->regs[GT_PCI0_CMD]      = 0x00010001;
+    s->regs[GT_PCI1_CMD]      = 0x00010001;
+#endif
+    s->regs[GT_PCI0_IACK]     = 0x00000000;
+    s->regs[GT_PCI1_IACK]     = 0x00000000;
+
+    gt64120_pci_mapping(s);
+}
+
+PCIBus *pci_gt64120_init(void *pic)
+{
+    GT64120State *s;
+    PCIDevice *d;
+    int gt64120;
+
+    s = qemu_mallocz(sizeof(GT64120State));
+    s->pci = qemu_mallocz(sizeof(GT64120PCIState));
+    gt64120_reset(s);
+
+    s->pci->bus = pci_register_bus(pci_gt64120_set_irq, pci_gt64120_map_irq,
+                                   pic, 144, 4);
+
+    gt64120 = cpu_register_io_memory(0, gt64120_read,
+                                     gt64120_write, s);
+    cpu_register_physical_memory(0x1be00000LL, 0x1000, gt64120);
+
+    d = pci_register_device(s->pci->bus, "GT64120 PCI Bus", sizeof(PCIDevice),
+                            0, NULL, NULL);
+
+    d->config[0x00] = 0xab; // vendor_id
+    d->config[0x01] = 0x11;
+    d->config[0x02] = 0x46; // device_id
+    d->config[0x03] = 0x20;
+    d->config[0x04] = 0x06;
+    d->config[0x05] = 0x00;
+    d->config[0x06] = 0x80;
+    d->config[0x07] = 0xa2;
+    d->config[0x08] = 0x10;
+    d->config[0x09] = 0x00;
+    d->config[0x0A] = 0x80;
+    d->config[0x0B] = 0x05;
+    d->config[0x0C] = 0x08;
+    d->config[0x0D] = 0x40;
+    d->config[0x0E] = 0x00;
+    d->config[0x0F] = 0x00;
+    d->config[0x17] = 0x08;
+    d->config[0x1B] = 0x1c;
+    d->config[0x1F] = 0x1f;
+    d->config[0x23] = 0x14;
+    d->config[0x27] = 0x14;
+    d->config[0x3D] = 0x01;
+
+    return s->pci->bus;
+}
index c747f106e9a420332d55395aadc2fda4b8a27b55..f8b5a984b54c2641d1abff8b854e0770e404fc96 100644 (file)
@@ -161,6 +161,13 @@ void pic_update_irq(PicState2 *s)
 #endif
         s->irq_request(s->irq_request_opaque, 1);
     }
+
+/* all targets should do this rather than acking the IRQ in the cpu */
+#if defined(TARGET_MIPS)
+    else {
+        s->irq_request(s->irq_request_opaque, 0);
+    }
+#endif
 }
 
 #ifdef DEBUG_IRQ_LATENCY
index 274dd8f8503c43757b3e72f280d373934077478e..2b58efb870f748229e10beffb711fc9cfa0c8e94 100644 (file)
  * THE SOFTWARE.
  */
 #include "vl.h"
-#include <pthread.h>
 
 /* debug IDE devices */
 //#define DEBUG_IDE
 //#define DEBUG_IDE_ATAPI
+//#define DEBUG_AIO
+#define USE_DMA_CDROM
 
 /* Bits of HD_STATUS */
 #define ERR_STAT               0x01
@@ -370,19 +371,20 @@ typedef struct IDEState {
 #define UDIDETCR0      0x73
 #define UDIDETCR1      0x7B
 
-typedef int IDEDMAFunc(IDEState *s, 
-                       target_phys_addr_t phys_addr, 
-                       int transfer_size1);
-
 typedef struct BMDMAState {
     uint8_t cmd;
     uint8_t status;
     uint32_t addr;
-
+    
     struct PCIIDEState *pci_dev;
     /* current transfer state */
+    uint32_t cur_addr;
+    uint32_t cur_prd_last;
+    uint32_t cur_prd_addr;
+    uint32_t cur_prd_len;
     IDEState *ide_if;
-    IDEDMAFunc *dma_cb;
+    BlockDriverCompletionFunc *dma_cb;
+    BlockDriverAIOCB *aiocb;
 } BMDMAState;
 
 typedef struct PCIIDEState {
@@ -392,89 +394,6 @@ typedef struct PCIIDEState {
     int type; /* see IDE_TYPE_xxx */
 } PCIIDEState;
 
-#define DMA_MULTI_THREAD
-
-#ifdef DMA_MULTI_THREAD
-
-static pthread_t ide_dma_thread;
-static int file_pipes[2];
-
-static void ide_dma_loop(BMDMAState *bm);
-static void dma_thread_loop(BMDMAState *bm);
-
-extern int suspend_requested;
-static void *dma_thread_func(void* opaque)
-{
-    BMDMAState* req;
-    fd_set fds;
-    int rv, nfds = file_pipes[0] + 1;
-    struct timeval tm;
-
-    while (1) {
-
-        /* Wait at most a second for the pipe to become readable */
-        FD_ZERO(&fds);
-        FD_SET(file_pipes[0], &fds);
-        tm.tv_sec = 1;
-        tm.tv_usec = 0;
-        rv = select(nfds, &fds, NULL, NULL, &tm);
-        
-        if (rv != 0) {
-            if (read(file_pipes[0], &req, sizeof(req)) == 0)
-                return NULL;
-            dma_thread_loop(req);
-        } else {
-            if (suspend_requested)  {
-                /* Need to tidy up the DMA thread so that we don't end up 
-                 * finishing operations after the domain's ioreqs are 
-                 * drained and its state saved */
-                return NULL;
-            }
-        }
-    }
-
-    return NULL;
-}
-
-static void dma_create_thread(void)
-{
-    int rt;
-    pthread_attr_t a;
-
-    if (pipe(file_pipes) != 0) {
-        fprintf(stderr, "create pipe failed\n");
-        exit(1);
-    }
-
-    if ((rt = pthread_attr_init(&a))
-        || (rt = pthread_attr_setdetachstate(&a, PTHREAD_CREATE_JOINABLE))) {
-        fprintf(stderr, "Oops, dma thread attr setup failed, errno=%d\n", rt);
-        exit(1);
-    }    
-    
-    if ((rt = pthread_create(&ide_dma_thread, &a, dma_thread_func, NULL))) {
-        fprintf(stderr, "Oops, dma thread creation failed, errno=%d\n", rt);
-        exit(1);
-    }
-}
-
-void ide_stop_dma_thread(void)
-{
-    int rc;
-    /* Make sure the IDE DMA thread is stopped */
-    if ( (rc = pthread_join(ide_dma_thread, NULL)) != 0 )
-    {
-        fprintf(stderr, "Oops, error collecting IDE DMA thread (%s)\n", 
-                strerror(rc));
-    }
-}
-
-#else
-void ide_stop_dma_thread(void)
-{
-}
-#endif /* DMA_MULTI_THREAD */
-
 #if defined(__ia64__)
 #include <xen/hvm/ioreq.h>
 
@@ -590,7 +509,8 @@ buffered_pio_read(IDEState *s, uint32_t addr, int size)
 #define buffered_pio_read(I,A,S)    do {} while (0)
 #endif
 
-static void ide_dma_start(IDEState *s, IDEDMAFunc *dma_cb);
+static void ide_dma_start(IDEState *s, BlockDriverCompletionFunc *dma_cb);
+static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret);
 
 static void padstr(char *str, const char *src, int len)
 {
@@ -713,10 +633,17 @@ static void ide_atapi_identify(IDEState *s)
     padstr((uint8_t *)(p + 23), QEMU_VERSION, 8); /* firmware version */
     padstr((uint8_t *)(p + 27), "QEMU CD-ROM", 40); /* model */
     put_le16(p + 48, 1); /* dword I/O (XXX: should not be set on CDROM) */
-    put_le16(p + 49, (1 << 11) | (1 << 9) | (1 << 8)); /* DMA and LBA supported */
+#ifdef USE_DMA_CDROM
+    put_le16(p + 49, 1 << 9 | 1 << 8); /* DMA and LBA supported */
+    put_le16(p + 53, 7); /* words 64-70, 54-58, 88 valid */
+    put_le16(p + 63, 7);  /* mdma0-2 supported */
+    put_le16(p + 64, 0x3f); /* PIO modes supported */
+#else
+    put_le16(p + 49, 1 << 9); /* LBA supported, no DMA */
     put_le16(p + 53, 3); /* words 64-70, 54-58 valid */
-    put_le16(p + 63, 0x07); /* mdma0-2 supported */
+    put_le16(p + 63, 0x103); /* DMA modes XXX: may be incorrect */
     put_le16(p + 64, 1); /* PIO modes */
+#endif
     put_le16(p + 65, 0xb4); /* minimum DMA multiword tx cycle time */
     put_le16(p + 66, 0xb4); /* recommended DMA multiword tx cycle time */
     put_le16(p + 67, 0x12c); /* minimum PIO cycle time without flow control */
@@ -726,7 +653,9 @@ static void ide_atapi_identify(IDEState *s)
     put_le16(p + 72, 30); /* in ns */
 
     put_le16(p + 80, 0x1e); /* support up to ATA/ATAPI-4 */
-
+#ifdef USE_DMA_CDROM
+    put_le16(p + 88, 0x3f | (1 << 13)); /* udma5 set and supported */
+#endif
     memcpy(s->identify_data, p, sizeof(s->identify_data));
     s->identify_set = 1;
 }
@@ -865,60 +794,101 @@ static void ide_sector_read(IDEState *s)
     }
 }
 
-static int ide_read_dma_cb(IDEState *s, 
-                           target_phys_addr_t phys_addr, 
-                           int transfer_size1)
+/* return 0 if buffer completed */
+static int dma_buf_rw(BMDMAState *bm, int is_write)
 {
-    int len, transfer_size, n;
-    int64_t sector_num;
+    IDEState *s = bm->ide_if;
+    struct {
+        uint32_t addr;
+        uint32_t size;
+    } prd;
+    int l, len;
 
-    transfer_size = transfer_size1;
-    while (transfer_size > 0) {
-        len = s->io_buffer_size - s->io_buffer_index;
-        if (len <= 0) {
-            /* transfert next data */
-            n = s->nsector;
-            if (n == 0)
-                break;
-            if (n > MAX_MULT_SECTORS)
-                n = MAX_MULT_SECTORS;
-            sector_num = ide_get_sector(s);
-            if (bdrv_read(s->bs, sector_num, s->io_buffer, n) != 0) {
-                ide_abort_command(s);
-                ide_set_irq(s);
+    for(;;) {
+        l = s->io_buffer_size - s->io_buffer_index;
+        if (l <= 0) 
+            break;
+        if (bm->cur_prd_len == 0) {
+            /* end of table (with a fail safe of one page) */
+            if (bm->cur_prd_last ||
+                (bm->cur_addr - bm->addr) >= 4096)
                 return 0;
+            cpu_physical_memory_read(bm->cur_addr, (uint8_t *)&prd, 8);
+            bm->cur_addr += 8;
+            prd.addr = le32_to_cpu(prd.addr);
+            prd.size = le32_to_cpu(prd.size);
+            len = prd.size & 0xfffe;
+            if (len == 0)
+                len = 0x10000;
+            bm->cur_prd_len = len;
+            bm->cur_prd_addr = prd.addr;
+            bm->cur_prd_last = (prd.size & 0x80000000);
+        }
+        if (l > bm->cur_prd_len)
+            l = bm->cur_prd_len;
+        if (l > 0) {
+            if (is_write) {
+                cpu_physical_memory_write(bm->cur_prd_addr, 
+                                          s->io_buffer + s->io_buffer_index, l);
+            } else {
+                cpu_physical_memory_read(bm->cur_prd_addr, 
+                                          s->io_buffer + s->io_buffer_index, l);
             }
-            s->io_buffer_index = 0;
-            s->io_buffer_size = n * 512;
-            len = s->io_buffer_size;
-            sector_num += n;
-            ide_set_sector(s, sector_num);
-            s->nsector -= n;
+            bm->cur_prd_addr += l;
+            bm->cur_prd_len -= l;
+            s->io_buffer_index += l;
         }
-        if (len > transfer_size)
-            len = transfer_size;
-        cpu_physical_memory_write(phys_addr, 
-                                  s->io_buffer + s->io_buffer_index, len);
-        s->io_buffer_index += len;
-        transfer_size -= len;
-        phys_addr += len;
     }
-    if (s->io_buffer_index >= s->io_buffer_size && s->nsector == 0) {
+    return 1;
+}
+
+/* XXX: handle errors */
+static void ide_read_dma_cb(void *opaque, int ret)
+{
+    BMDMAState *bm = opaque;
+    IDEState *s = bm->ide_if;
+    int n;
+    int64_t sector_num;
+
+    n = s->io_buffer_size >> 9;
+    sector_num = ide_get_sector(s);
+    if (n > 0) {
+        sector_num += n;
+        ide_set_sector(s, sector_num);
+        s->nsector -= n;
+        if (dma_buf_rw(bm, 1) == 0)
+            goto eot;
+    }
+
+    /* end of transfer ? */
+    if (s->nsector == 0) {
         s->status = READY_STAT | SEEK_STAT;
-#ifndef DMA_MULTI_THREAD
         ide_set_irq(s);
-#endif /* !DMA_MULTI_THREAD */
-#ifdef DEBUG_IDE_ATAPI
-        printf("dma status=0x%x\n", s->status);
-#endif
-        return 0;
+    eot:
+        bm->status &= ~BM_STATUS_DMAING;
+        bm->status |= BM_STATUS_INT;
+        bm->dma_cb = NULL;
+        bm->ide_if = NULL;
+        bm->aiocb = NULL;
+        return;
     }
-    return transfer_size1 - transfer_size;
+
+    /* launch next transfer */
+    n = s->nsector;
+    if (n > MAX_MULT_SECTORS)
+        n = MAX_MULT_SECTORS;
+    s->io_buffer_index = 0;
+    s->io_buffer_size = n * 512;
+#ifdef DEBUG_AIO
+    printf("aio_read: sector_num=%lld n=%d\n", sector_num, n);
+#endif
+    bm->aiocb = bdrv_aio_read(s->bs, sector_num, s->io_buffer, n, 
+                              ide_read_dma_cb, bm);
 }
 
 static void ide_sector_read_dma(IDEState *s)
 {
-    s->status = READY_STAT | SEEK_STAT | DRQ_STAT;
+    s->status = READY_STAT | SEEK_STAT | DRQ_STAT | BUSY_STAT;
     s->io_buffer_index = 0;
     s->io_buffer_size = 0;
     ide_dma_start(s, ide_read_dma_cb);
@@ -980,84 +950,56 @@ static void ide_sector_write(IDEState *s)
     }
 }
 
-static int ide_write_dma_cb(IDEState *s, 
-                            target_phys_addr_t phys_addr, 
-                            int transfer_size1)
+/* XXX: handle errors */
+static void ide_write_dma_cb(void *opaque, int ret)
 {
-    int len, transfer_size, n;
+    BMDMAState *bm = opaque;
+    IDEState *s = bm->ide_if;
+    int n;
     int64_t sector_num;
 
-    transfer_size = transfer_size1;
-    for(;;) {
-        len = s->io_buffer_size - s->io_buffer_index;
-        if (len == 0) {
-            n = s->io_buffer_size >> 9;
-            sector_num = ide_get_sector(s);
-            if (bdrv_write(s->bs, sector_num, s->io_buffer, 
-                          s->io_buffer_size >> 9) != 0) {
-                ide_abort_command(s);
-                ide_set_irq(s);
-                return 0;
-            }
-
-            sector_num += n;
-            ide_set_sector(s, sector_num);
-            s->nsector -= n;
-            n = s->nsector;
-            if (n == 0) {
-                /* end of transfer */
-                s->status = READY_STAT | SEEK_STAT;
-#ifdef TARGET_I386
-                if (win2k_install_hack && ((++s->irq_count % 16) == 0)) {
-                    /* It seems there is a bug in the Windows 2000 installer 
-                       HDD IDE driver which fills the disk with empty logs 
-                       when the IDE write IRQ comes too early. This hack tries 
-                       to correct that at the expense of slower write 
-                       performances. Use this option _only_ to install Windows 
-                       2000. You must disable it for normal use. */
-                    qemu_mod_timer(s->sector_write_timer, 
-                            qemu_get_clock(vm_clock) + (ticks_per_sec / 1000));
-                } else 
-#endif
-#ifndef DMA_MULTI_THREAD
-                    ide_set_irq(s);
-#else  /* !DMA_MULTI_THREAD */
-                    ;
-#endif /* DMA_MULTI_THREAD */
-                return 0;
-            }
-            if (n > MAX_MULT_SECTORS)
-                n = MAX_MULT_SECTORS;
-            s->io_buffer_index = 0;
-            s->io_buffer_size = n * 512;
-            len = s->io_buffer_size;
-        }
-        if (transfer_size <= 0)
-            break;
-        if (len > transfer_size)
-            len = transfer_size;
-        cpu_physical_memory_read(phys_addr, 
-                                 s->io_buffer + s->io_buffer_index, len);
-        s->io_buffer_index += len;
-        transfer_size -= len;
-        phys_addr += len;
+    n = s->io_buffer_size >> 9;
+    sector_num = ide_get_sector(s);
+    if (n > 0) {
+        sector_num += n;
+        ide_set_sector(s, sector_num);
+        s->nsector -= n;
     }
-    /* Ensure the data hit disk before telling the guest OS so. */
-    if (!s->write_cache)
-        bdrv_flush(s->bs);
 
-    return transfer_size1 - transfer_size;
-}
+    /* end of transfer ? */
+    if (s->nsector == 0) {
+        s->status = READY_STAT | SEEK_STAT;
+        ide_set_irq(s);
+    eot:
+        bm->status &= ~BM_STATUS_DMAING;
+        bm->status |= BM_STATUS_INT;
+        bm->dma_cb = NULL;
+        bm->ide_if = NULL;
+        bm->aiocb = NULL;
+        return;
+    }
 
-static void ide_sector_write_dma(IDEState *s)
-{
-    int n;
-    s->status = READY_STAT | SEEK_STAT | DRQ_STAT;
+    /* launch next transfer */
     n = s->nsector;
     if (n > MAX_MULT_SECTORS)
         n = MAX_MULT_SECTORS;
     s->io_buffer_index = 0;
     s->io_buffer_size = n * 512;
+
+    if (dma_buf_rw(bm, 0) == 0)
+        goto eot;
+#ifdef DEBUG_AIO
+    printf("aio_write: sector_num=%lld n=%d\n", sector_num, n);
+#endif
+    bm->aiocb = bdrv_aio_write(s->bs, sector_num, s->io_buffer, n, 
+                               ide_write_dma_cb, bm);
+}
+
+static void ide_sector_write_dma(IDEState *s)
+{
+    s->status = READY_STAT | SEEK_STAT | DRQ_STAT | BUSY_STAT;
+    s->io_buffer_index = 0;
+    s->io_buffer_size = 0;
     ide_dma_start(s, ide_write_dma_cb);
 }
 
@@ -1114,38 +1056,61 @@ static void lba_to_msf(uint8_t *buf, int lba)
     buf[2] = lba % 75;
 }
 
-static void cd_read_sector(BlockDriverState *bs, int lba, uint8_t *buf, 
+static void cd_data_to_raw(uint8_t *buf, int lba)
+{
+    /* sync bytes */
+    buf[0] = 0x00;
+    memset(buf + 1, 0xff, 10);
+    buf[11] = 0x00;
+    buf += 12;
+    /* MSF */
+    lba_to_msf(buf, lba);
+    buf[3] = 0x01; /* mode 1 data */
+    buf += 4;
+    /* data */
+    buf += 2048;
+    /* XXX: ECC not computed */
+    memset(buf, 0, 288);
+}
+
+static int cd_read_sector(BlockDriverState *bs, int lba, uint8_t *buf, 
                            int sector_size)
 {
+    int ret;
+
     switch(sector_size) {
     case 2048:
-        bdrv_read(bs, (int64_t)lba << 2, buf, 4);
+        ret = bdrv_read(bs, (int64_t)lba << 2, buf, 4);
         break;
     case 2352:
-        /* sync bytes */
-        buf[0] = 0x00;
-        memset(buf + 1, 0xff, 10);
-        buf[11] = 0x00;
-        buf += 12;
-        /* MSF */
-        lba_to_msf(buf, lba);
-        buf[3] = 0x01; /* mode 1 data */
-        buf += 4;
-        /* data */
-        bdrv_read(bs, (int64_t)lba << 2, buf, 4);
-        buf += 2048;
-        /* ECC */
-        memset(buf, 0, 288);
+        ret = bdrv_read(bs, (int64_t)lba << 2, buf + 16, 4);
+        if (ret < 0)
+            return ret;
+        cd_data_to_raw(buf, lba);
         break;
     default:
+        ret = -EIO;
         break;
     }
+    return ret;
+}
+
+static void ide_atapi_io_error(IDEState *s, int ret)
+{
+    /* XXX: handle more errors */
+    if (ret == -ENOMEDIUM) {
+        ide_atapi_cmd_error(s, SENSE_NOT_READY, 
+                            ASC_MEDIUM_NOT_PRESENT);
+    } else {
+        ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, 
+                            ASC_LOGICAL_BLOCK_OOR);
+    }
 }
 
 /* The whole ATAPI transfer logic is handled in this function */
 static void ide_atapi_cmd_reply_end(IDEState *s)
 {
-    int byte_count_limit, size;
+    int byte_count_limit, size, ret;
 #ifdef DEBUG_IDE_ATAPI
     printf("reply: tx_size=%d elem_tx_size=%d index=%d\n", 
            s->packet_transfer_size,
@@ -1164,7 +1129,12 @@ static void ide_atapi_cmd_reply_end(IDEState *s)
     } else {
         /* see if a new sector must be read */
         if (s->lba != -1 && s->io_buffer_index >= s->cd_sector_size) {
-            cd_read_sector(s->bs, s->lba, s->io_buffer, s->cd_sector_size);
+            ret = cd_read_sector(s->bs, s->lba, s->io_buffer, s->cd_sector_size);
+            if (ret < 0) {
+                ide_transfer_stop(s);
+                ide_atapi_io_error(s, ret);
+                return;
+            }
             s->lba++;
             s->io_buffer_index = 0;
         }
@@ -1223,11 +1193,17 @@ static void ide_atapi_cmd_reply(IDEState *s, int size, int max_size)
         size = max_size;
     s->lba = -1; /* no sector read */
     s->packet_transfer_size = size;
+    s->io_buffer_size = size;    /* dma: send the reply data as one chunk */
     s->elementary_transfer_size = 0;
     s->io_buffer_index = 0;
 
-    s->status = READY_STAT;
-    ide_atapi_cmd_reply_end(s);
+    if (s->atapi_dma) {
+       s->status = READY_STAT | DRQ_STAT;
+       ide_dma_start(s, ide_atapi_cmd_read_dma_cb);
+    } else {
+       s->status = READY_STAT;
+       ide_atapi_cmd_reply_end(s);
+    }
 }
 
 /* start a CD-CDROM read command */
@@ -1245,48 +1221,78 @@ static void ide_atapi_cmd_read_pio(IDEState *s, int lba, int nb_sectors,
 }
 
 /* ATAPI DMA support */
-static int ide_atapi_cmd_read_dma_cb(IDEState *s, 
-                                     target_phys_addr_t phys_addr, 
-                                     int transfer_size1)
+
+/* XXX: handle read errors */
+static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret)
 {
-    int len, transfer_size;
-    
-    transfer_size = transfer_size1;
-    while (transfer_size > 0) {
-#ifdef DEBUG_IDE_ATAPI
-        printf("transfer_size: %d phys_addr=%08x\n", transfer_size, phys_addr);
-#endif
-        if (s->packet_transfer_size <= 0)
-            break;
-        len = s->cd_sector_size - s->io_buffer_index;
-        if (len <= 0) {
-            /* transfert next data */
-            cd_read_sector(s->bs, s->lba, s->io_buffer, s->cd_sector_size);
-            s->lba++;
-            s->io_buffer_index = 0;
-            len = s->cd_sector_size;
-        }
-        if (len > transfer_size)
-            len = transfer_size;
-        cpu_physical_memory_write(phys_addr, 
-                                  s->io_buffer + s->io_buffer_index, len);
-        s->packet_transfer_size -= len;
-        s->io_buffer_index += len;
-        transfer_size -= len;
-        phys_addr += len;
+    BMDMAState *bm = opaque;
+    IDEState *s = bm->ide_if;
+    int data_offset, n;
+
+    if (ret < 0) {
+        ide_atapi_io_error(s, ret);
+        goto eot;
+    }
+
+    if (s->io_buffer_size > 0) {
+       /*
+        * For a cdrom read sector command (s->lba != -1),
+        * adjust the lba for the next s->io_buffer_size chunk
+        * and dma the current chunk.
+        * For a command != read (s->lba == -1), just transfer
+        * the reply data.
+        */
+       if (s->lba != -1) {
+           if (s->cd_sector_size == 2352) {
+               n = 1;
+               cd_data_to_raw(s->io_buffer, s->lba);
+           } else {
+               n = s->io_buffer_size >> 11;
+           }
+           s->lba += n;
+       }
+        s->packet_transfer_size -= s->io_buffer_size;
+        if (dma_buf_rw(bm, 1) == 0)
+            goto eot;
     }
+
     if (s->packet_transfer_size <= 0) {
         s->status = READY_STAT;
         s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
-#ifndef DMA_MULTI_THREAD
         ide_set_irq(s);
-#endif /* !DMA_MULTI_THREAD */
-#ifdef DEBUG_IDE_ATAPI
-        printf("dma status=0x%x\n", s->status);
+    eot:
+        bm->status &= ~BM_STATUS_DMAING;
+        bm->status |= BM_STATUS_INT;
+        bm->dma_cb = NULL;
+        bm->ide_if = NULL;
+        bm->aiocb = NULL;
+        return;
+    }
+    
+    s->io_buffer_index = 0;
+    if (s->cd_sector_size == 2352) {
+        n = 1;
+        s->io_buffer_size = s->cd_sector_size;
+        data_offset = 16;
+    } else {
+        n = s->packet_transfer_size >> 11;
+        if (n > (MAX_MULT_SECTORS / 4))
+            n = (MAX_MULT_SECTORS / 4);
+        s->io_buffer_size = n * 2048;
+        data_offset = 0;
+    }
+#ifdef DEBUG_AIO
+    printf("aio_read_cd: lba=%u n=%d\n", s->lba, n);
 #endif
-        return 0;
+    bm->aiocb = bdrv_aio_read(s->bs, (int64_t)s->lba << 2, 
+                              s->io_buffer + data_offset, n * 4, 
+                              ide_atapi_cmd_read_dma_cb, bm);
+    if (!bm->aiocb) {
+        /* Note: media not present is the most likely case */
+        ide_atapi_cmd_error(s, SENSE_NOT_READY, 
+                            ASC_MEDIUM_NOT_PRESENT);
+        goto eot;
     }
-    return transfer_size1 - transfer_size;
 }
 
 /* start a CD-CDROM read command with DMA */
@@ -1296,10 +1302,12 @@ static void ide_atapi_cmd_read_dma(IDEState *s, int lba, int nb_sectors,
 {
     s->lba = lba;
     s->packet_transfer_size = nb_sectors * sector_size;
-    s->io_buffer_index = sector_size;
+    s->io_buffer_index = 0;
+    s->io_buffer_size = 0;
     s->cd_sector_size = sector_size;
 
-    s->status = READY_STAT | DRQ_STAT;
+    /* XXX: check if BUSY_STAT should be set */
+    s->status = READY_STAT | DRQ_STAT | BUSY_STAT;
     ide_dma_start(s, ide_atapi_cmd_read_dma_cb);
 }
 
@@ -1307,7 +1315,8 @@ static void ide_atapi_cmd_read(IDEState *s, int lba, int nb_sectors,
                                int sector_size)
 {
 #ifdef DEBUG_IDE_ATAPI
-    printf("read: LBA=%d nb_sectors=%d\n", lba, nb_sectors);
+    printf("read %s: LBA=%d nb_sectors=%d\n", s->atapi_dma ? "dma" : "pio",
+       lba, nb_sectors);
 #endif
     if (s->atapi_dma) {
         ide_atapi_cmd_read_dma(s, lba, nb_sectors, sector_size);
@@ -1442,11 +1451,6 @@ static void ide_atapi_cmd(IDEState *s)
         {
             int nb_sectors, lba;
 
-            if (!bdrv_is_inserted(s->bs)) {
-                ide_atapi_cmd_error(s, SENSE_NOT_READY, 
-                                    ASC_MEDIUM_NOT_PRESENT);
-                break;
-            }
             if (packet[0] == GPCMD_READ_10)
                 nb_sectors = ube16_to_cpu(packet + 7);
             else
@@ -1456,11 +1460,6 @@ static void ide_atapi_cmd(IDEState *s)
                 ide_atapi_cmd_ok(s);
                 break;
             }
-            if (((int64_t)(lba + nb_sectors) << 2) > s->nb_sectors) {
-                ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, 
-                                    ASC_LOGICAL_BLOCK_OOR);
-                break;
-            }
             ide_atapi_cmd_read(s, lba, nb_sectors, 2048);
         }
         break;
@@ -1468,22 +1467,12 @@ static void ide_atapi_cmd(IDEState *s)
         {
             int nb_sectors, lba, transfer_request;
 
-            if (!bdrv_is_inserted(s->bs)) {
-                ide_atapi_cmd_error(s, SENSE_NOT_READY, 
-                                    ASC_MEDIUM_NOT_PRESENT);
-                break;
-            }
             nb_sectors = (packet[6] << 16) | (packet[7] << 8) | packet[8];
             lba = ube32_to_cpu(packet + 2);
             if (nb_sectors == 0) {
                 ide_atapi_cmd_ok(s);
                 break;
             }
-            if (((int64_t)(lba + nb_sectors) << 2) > s->nb_sectors) {
-                ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, 
-                                    ASC_LOGICAL_BLOCK_OOR);
-                break;
-            }
             transfer_request = packet[9];
             switch(transfer_request & 0xf8) {
             case 0x00:
@@ -1508,13 +1497,17 @@ static void ide_atapi_cmd(IDEState *s)
     case GPCMD_SEEK:
         {
             int lba;
-            if (!bdrv_is_inserted(s->bs)) {
+            int64_t total_sectors;
+
+            bdrv_get_geometry(s->bs, &total_sectors);
+            total_sectors >>= 2;
+            if (total_sectors <= 0) {
                 ide_atapi_cmd_error(s, SENSE_NOT_READY, 
                                     ASC_MEDIUM_NOT_PRESENT);
                 break;
             }
             lba = ube32_to_cpu(packet + 2);
-            if (((int64_t)lba << 2) > s->nb_sectors) {
+            if (lba >= total_sectors) {
                 ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, 
                                     ASC_LOGICAL_BLOCK_OOR);
                 break;
@@ -1530,7 +1523,10 @@ static void ide_atapi_cmd(IDEState *s)
             
             if (eject && !start) {
                 /* eject the disk */
-                bdrv_close(s->bs);
+                bdrv_eject(s->bs, 1);
+            } else if (eject && start) {
+                /* close the tray */
+                bdrv_eject(s->bs, 0);
             }
             ide_atapi_cmd_ok(s);
         }
@@ -1551,8 +1547,11 @@ static void ide_atapi_cmd(IDEState *s)
     case GPCMD_READ_TOC_PMA_ATIP:
         {
             int format, msf, start_track, len;
+            int64_t total_sectors;
 
-            if (!bdrv_is_inserted(s->bs)) {
+            bdrv_get_geometry(s->bs, &total_sectors);
+            total_sectors >>= 2;
+            if (total_sectors <= 0) {
                 ide_atapi_cmd_error(s, SENSE_NOT_READY, 
                                     ASC_MEDIUM_NOT_PRESENT);
                 break;
@@ -1563,7 +1562,7 @@ static void ide_atapi_cmd(IDEState *s)
             start_track = packet[6];
             switch(format) {
             case 0:
-                len = cdrom_read_toc(s->nb_sectors >> 2, buf, msf, start_track);
+                len = cdrom_read_toc(total_sectors, buf, msf, start_track);
                 if (len < 0)
                     goto error_cmd;
                 ide_atapi_cmd_reply(s, len, max_len);
@@ -1577,7 +1576,7 @@ static void ide_atapi_cmd(IDEState *s)
                 ide_atapi_cmd_reply(s, 12, max_len);
                 break;
             case 2:
-                len = cdrom_read_toc_raw(s->nb_sectors >> 2, buf, msf, start_track);
+                len = cdrom_read_toc_raw(total_sectors, buf, msf, start_track);
                 if (len < 0)
                     goto error_cmd;
                 ide_atapi_cmd_reply(s, len, max_len);
@@ -1591,15 +1590,21 @@ static void ide_atapi_cmd(IDEState *s)
         }
         break;
     case GPCMD_READ_CDVD_CAPACITY:
-        if (!bdrv_is_inserted(s->bs)) {
-            ide_atapi_cmd_error(s, SENSE_NOT_READY, 
-                                ASC_MEDIUM_NOT_PRESENT);
-            break;
+        {
+            int64_t total_sectors;
+
+            bdrv_get_geometry(s->bs, &total_sectors);
+            total_sectors >>= 2;
+            if (total_sectors <= 0) {
+                ide_atapi_cmd_error(s, SENSE_NOT_READY, 
+                                    ASC_MEDIUM_NOT_PRESENT);
+                break;
+            }
+            /* NOTE: it is really the number of sectors minus 1 */
+            cpu_to_ube32(buf, total_sectors - 1);
+            cpu_to_ube32(buf + 4, 2048);
+            ide_atapi_cmd_reply(s, 8, 8);
         }
-        /* NOTE: it is really the number of sectors minus 1 */
-        cpu_to_ube32(buf, (s->nb_sectors >> 2) - 1);
-        cpu_to_ube32(buf + 4, 2048);
-        ide_atapi_cmd_reply(s, 8, 8);
         break;
     case GPCMD_INQUIRY:
         max_len = packet[4];
@@ -2225,7 +2230,7 @@ static void ide_init2(IDEState *ide_state,
 {
     IDEState *s;
     static int drive_serial = 1;
-    int i, cylinders, heads, secs, translation;
+    int i, cylinders, heads, secs, translation, lba_detected = 0;
     int64_t nb_sectors;
 
     for(i = 0; i < 2; i++) {
@@ -2239,6 +2244,7 @@ static void ide_init2(IDEState *ide_state,
             s->nb_sectors = nb_sectors;
             /* if a geometry hint is available, use it */
             bdrv_get_geometry_hint(s->bs, &cylinders, &heads, &secs);
+            translation = bdrv_get_translation_hint(s->bs);
             if (cylinders != 0) {
                 s->cylinders = cylinders;
                 s->heads = heads;
@@ -2249,6 +2255,7 @@ static void ide_init2(IDEState *ide_state,
                         /* if heads > 16, it means that a BIOS LBA
                            translation was active, so the default
                            hardware geometry is OK */
+                        lba_detected = 1;
                         goto default_geometry;
                     } else {
                         s->cylinders = cylinders;
@@ -2256,7 +2263,6 @@ static void ide_init2(IDEState *ide_state,
                         s->sectors = secs;
                         /* disable any translation to be in sync with
                            the logical geometry */
-                        translation = bdrv_get_translation_hint(s->bs);
                         if (translation == BIOS_ATA_TRANSLATION_AUTO) {
                             bdrv_set_translation_hint(s->bs,
                                                       BIOS_ATA_TRANSLATION_NONE);
@@ -2273,12 +2279,21 @@ static void ide_init2(IDEState *ide_state,
                     s->cylinders = cylinders;
                     s->heads = 16;
                     s->sectors = 63;
+                    if ((lba_detected == 1) && (translation == BIOS_ATA_TRANSLATION_AUTO)) {
+                      if ((s->cylinders * s->heads) <= 131072) {
+                        bdrv_set_translation_hint(s->bs,
+                                                  BIOS_ATA_TRANSLATION_LARGE);
+                      } else {
+                        bdrv_set_translation_hint(s->bs,
+                                                  BIOS_ATA_TRANSLATION_LBA);
+                      }
+                    }
                 }
                 bdrv_set_geometry_hint(s->bs, s->cylinders, s->heads, s->sectors);
             }
             if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) {
                 s->is_cdrom = 1;
-                bdrv_set_change_cb(s->bs, cdrom_change_cb, s);
+               bdrv_set_change_cb(s->bs, cdrom_change_cb, s);
             }
         }
         s->drive_serial = drive_serial++;
@@ -2353,77 +2368,18 @@ static void ide_map(PCIDevice *pci_dev, int region_num,
     }
 }
 
-static void ide_dma_finish(BMDMAState *bm)
-{
-    IDEState *s = bm->ide_if;
-
-    bm->status &= ~BM_STATUS_DMAING;
-    bm->status |= BM_STATUS_INT;
-    bm->dma_cb = NULL;
-    bm->ide_if = NULL;
-#ifdef DMA_MULTI_THREAD
-    ide_set_irq(s);
-#endif /* DMA_MULTI_THREAD */
-}
-
-/* XXX: full callback usage to prepare non blocking I/Os support -
-   error handling */
-#ifdef DMA_MULTI_THREAD
-static void ide_dma_loop(BMDMAState *bm)
-{
-    write(file_pipes[1], &bm, sizeof(bm));
-}
-static void dma_thread_loop(BMDMAState *bm)
-#else  /* DMA_MULTI_THREAD */
-static void ide_dma_loop(BMDMAState *bm)
-#endif /* !DMA_MULTI_THREAD */
-{
-    struct {
-        uint32_t addr;
-        uint32_t size;
-    } prd;
-    target_phys_addr_t cur_addr;
-    int len, i, len1;
-
-    cur_addr = bm->addr;
-    /* at most one page to avoid hanging if erroneous parameters */
-    for(i = 0; i < 512; i++) {
-        cpu_physical_memory_read(cur_addr, (uint8_t *)&prd, 8);
-        prd.addr = le32_to_cpu(prd.addr);
-        prd.size = le32_to_cpu(prd.size);
-#ifdef DEBUG_IDE
-        printf("ide: dma: prd: %08x: addr=0x%08x size=0x%08x\n", 
-               (int)cur_addr, prd.addr, prd.size);
-#endif
-        len = prd.size & 0xfffe;
-        if (len == 0)
-            len = 0x10000;
-        while (len > 0) {
-            len1 = bm->dma_cb(bm->ide_if, prd.addr, len);
-            if (len1 == 0)
-                goto the_end;
-            prd.addr += len1;
-            len -= len1;
-        }
-        /* end of transfer */
-        if (prd.size & 0x80000000)
-            break;
-        cur_addr += 8;
-    }
-    /* end of transfer */
- the_end:
-    ide_dma_finish(bm);
-}
-
-static void ide_dma_start(IDEState *s, IDEDMAFunc *dma_cb)
+static void ide_dma_start(IDEState *s, BlockDriverCompletionFunc *dma_cb)
 {
     BMDMAState *bm = s->bmdma;
     if(!bm)
         return;
     bm->ide_if = s;
     bm->dma_cb = dma_cb;
+    bm->cur_prd_last = 0;
+    bm->cur_prd_addr = 0;
+    bm->cur_prd_len = 0;
     if (bm->status & BM_STATUS_DMAING) {
-        ide_dma_loop(bm);
+        bm->dma_cb(bm, 0);
     }
 }
 
@@ -2435,14 +2391,28 @@ static void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val)
 #endif
     if (!(val & BM_CMD_START)) {
         /* XXX: do it better */
-        bm->status &= ~BM_STATUS_DMAING;
+        if (bm->status & BM_STATUS_DMAING) {
+            bm->status &= ~BM_STATUS_DMAING;
+            /* cancel DMA request */
+            bm->ide_if = NULL;
+            bm->dma_cb = NULL;
+            if (bm->aiocb) {
+#ifdef DEBUG_AIO
+                printf("aio_cancel\n");
+#endif
+                bdrv_aio_cancel(bm->aiocb);
+                bm->aiocb = NULL;
+            }
+        }
         bm->cmd = val & 0x09;
     } else {
-        bm->status |= BM_STATUS_DMAING;
+        if (!(bm->status & BM_STATUS_DMAING)) {
+            bm->status |= BM_STATUS_DMAING;
+            /* start dma transfer if possible */
+            if (bm->dma_cb)
+                bm->dma_cb(bm, 0);
+        }
         bm->cmd = val & 0x09;
-        /* start dma transfer if possible */
-        if (bm->dma_cb)
-            ide_dma_loop(bm);
     }
 }
 
@@ -2537,6 +2507,7 @@ static void bmdma_addr_writel(void *opaque, uint32_t addr, uint32_t val)
     printf("%s: 0x%08x\n", __func__, val);
 #endif
     bm->addr = val & ~3;
+    bm->cur_addr = bm->addr;
 }
 
 static void bmdma_map(PCIDevice *pci_dev, int region_num, 
@@ -2638,9 +2609,6 @@ void pci_cmd646_ide_init(PCIBus *bus, BlockDriverState **hd_table,
               cmd646_set_irq, d, 0);
     ide_init2(&d->ide_if[2], hd_table[2], hd_table[3],
               cmd646_set_irq, d, 1);
-#ifdef DMA_MULTI_THREAD    
-    dma_create_thread();
-#endif /* DMA_MULTI_THREAD */
 }
 
 static void pci_ide_save(QEMUFile* f, void *opaque)
@@ -2648,6 +2616,8 @@ static void pci_ide_save(QEMUFile* f, void *opaque)
     PCIIDEState *d = opaque;
     int i;
 
+    pci_device_save(&d->dev, f);
+
     for(i = 0; i < 2; i++) {
         BMDMAState *bm = &d->bmdma[i];
         qemu_put_8s(f, &bm->cmd);
@@ -2673,7 +2643,6 @@ static void pci_ide_save(QEMUFile* f, void *opaque)
         if (s->identify_set) {
             qemu_put_buffer(f, (const uint8_t *)s->identify_data, 512);
         }
-        qemu_put_8s(f, &s->write_cache);
         qemu_put_8s(f, &s->feature);
         qemu_put_8s(f, &s->error);
         qemu_put_be32s(f, &s->nsector);
@@ -2702,6 +2671,9 @@ static int pci_ide_load(QEMUFile* f, void *opaque, int version_id)
 
     if (version_id != 1)
         return -EINVAL;
+    ret = pci_device_load(&d->dev, f);
+    if (ret < 0)
+        return ret;
 
     for(i = 0; i < 2; i++) {
         BMDMAState *bm = &d->bmdma[i];
@@ -2728,7 +2700,6 @@ static int pci_ide_load(QEMUFile* f, void *opaque, int version_id)
         if (s->identify_set) {
             qemu_get_buffer(f, (uint8_t *)s->identify_data, 512);
         }
-        qemu_get_8s(f, &s->write_cache);
         qemu_get_8s(f, &s->feature);
         qemu_get_8s(f, &s->error);
         qemu_get_be32s(f, &s->nsector);
@@ -2747,15 +2718,64 @@ static int pci_ide_load(QEMUFile* f, void *opaque, int version_id)
         qemu_get_8s(f, &s->sense_key);
         qemu_get_8s(f, &s->asc);
         /* XXX: if a transfer is pending, we do not save it yet */
-        if (s->status & (DRQ_STAT|BUSY_STAT)) {
-            /* Tell the guest that its transfer has gone away */
-            ide_abort_command(s);
-            ide_set_irq(s);
-        }
     }
     return 0;
 }
 
+static void piix3_reset(PCIIDEState *d)
+{
+    uint8_t *pci_conf = d->dev.config;
+
+    pci_conf[0x04] = 0x00;
+    pci_conf[0x05] = 0x00;
+    pci_conf[0x06] = 0x80; /* FBC */
+    pci_conf[0x07] = 0x02; // PCI_status_devsel_medium
+    pci_conf[0x20] = 0x01; /* BMIBA: 20-23h */
+}
+
+void pci_piix_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn)
+{
+    PCIIDEState *d;
+    uint8_t *pci_conf;
+    
+    /* register a function 1 of PIIX */
+    d = (PCIIDEState *)pci_register_device(bus, "PIIX IDE", 
+                                           sizeof(PCIIDEState),
+                                           devfn,
+                                           NULL, NULL);
+    d->type = IDE_TYPE_PIIX3;
+
+    pci_conf = d->dev.config;
+    pci_conf[0x00] = 0x86; // Intel
+    pci_conf[0x01] = 0x80;
+    pci_conf[0x02] = 0x30;
+    pci_conf[0x03] = 0x12;
+    pci_conf[0x08] = 0x02; // Step A1
+    pci_conf[0x09] = 0x80; // legacy ATA mode
+    pci_conf[0x0a] = 0x01; // class_sub = PCI_IDE
+    pci_conf[0x0b] = 0x01; // class_base = PCI_mass_storage
+    pci_conf[0x0e] = 0x00; // header_type
+    pci_conf[0x2c] = 0x53; /* subsystem vendor: XenSource */
+    pci_conf[0x2d] = 0x58;
+    pci_conf[0x2e] = 0x01; /* subsystem device */
+    pci_conf[0x2f] = 0x00;
+
+    piix3_reset(d);
+
+    pci_register_io_region((PCIDevice *)d, 4, 0x10, 
+                           PCI_ADDRESS_SPACE_IO, bmdma_map);
+
+    ide_init2(&d->ide_if[0], hd_table[0], hd_table[1],
+              pic_set_irq_new, isa_pic, 14);
+    ide_init2(&d->ide_if[2], hd_table[2], hd_table[3],
+              pic_set_irq_new, isa_pic, 15);
+    ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6);
+    ide_init_ioport(&d->ide_if[2], 0x170, 0x376);
+
+    buffered_pio_init();
+
+    register_savevm("ide", 0, 1, pci_ide_save, pci_ide_load, d);
+}
 
 /* hd_table must contain 4 block drivers */
 /* NOTE: for the PIIX3, the IRQs and IOports are hardcoded */
@@ -2780,10 +2800,8 @@ void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn)
     pci_conf[0x0a] = 0x01; // class_sub = PCI_IDE
     pci_conf[0x0b] = 0x01; // class_base = PCI_mass_storage
     pci_conf[0x0e] = 0x00; // header_type
-    pci_conf[0x2c] = 0x53; /* subsystem vendor: XenSource */
-    pci_conf[0x2d] = 0x58;
-    pci_conf[0x2e] = 0x01; /* subsystem device */
-    pci_conf[0x2f] = 0x00;
+
+    piix3_reset(d);
 
     pci_register_io_region((PCIDevice *)d, 4, 0x10, 
                            PCI_ADDRESS_SPACE_IO, bmdma_map);
@@ -2797,12 +2815,7 @@ void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn)
 
     buffered_pio_init();
 
-    register_savevm("ide_pci", 0, 1, generic_pci_save, generic_pci_load, d);
     register_savevm("ide", 0, 1, pci_ide_save, pci_ide_load, d);
-
-#ifdef DMA_MULTI_THREAD    
-    dma_create_thread();
-#endif //DMA_MULTI_THREAD    
 }
 
 /***********************************************************/
index f438af733db1ff61b0c2c1f9ee91199048f01236..4e5f4ac9f722729b1f871f726c63b40f5f3016d1 100644 (file)
@@ -325,7 +325,7 @@ static uint32_t icp_pic_read(void *opaque, target_phys_addr_t offset)
     case 5: /* INT_SOFTCLR */
     case 11: /* FRQ_ENABLECLR */
     default:
-        printf ("icp_pic_read: Bad register offset 0x%x\n", offset);
+        printf ("icp_pic_read: Bad register offset 0x%x\n", (int)offset);
         return 0;
     }
 }
@@ -362,7 +362,7 @@ static void icp_pic_write(void *opaque, target_phys_addr_t offset,
     case 8: /* FRQ_STATUS */
     case 9: /* FRQ_RAWSTAT */
     default:
-        printf ("icp_pic_write: Bad register offset 0x%x\n", offset);
+        printf ("icp_pic_write: Bad register offset 0x%x\n", (int)offset);
         return;
     }
     icp_pic_update(s);
@@ -509,7 +509,7 @@ static void integratorcp_init(int ram_size, int vga_ram_size, int boot_device,
     }
     pl110_init(ds, 0xc0000000, pic, 22, 0);
 
-    arm_load_kernel(ram_size, kernel_filename, kernel_cmdline,
+    arm_load_kernel(env, ram_size, kernel_filename, kernel_cmdline,
                     initrd_filename, 0x113);
 }
 
index 140d8e17e70a6454181339f20332d14ad7a43d61..e264f0cadf70c852fc0a5a5a16256feca18cba22 100644 (file)
@@ -190,21 +190,54 @@ static CPUWriteMemoryFunc *iommu_mem_write[3] = {
     iommu_mem_writew,
 };
 
-uint32_t iommu_translate_local(void *opaque, uint32_t addr)
+static uint32_t iommu_page_get_flags(IOMMUState *s, uint32_t addr)
 {
-    IOMMUState *s = opaque;
-    uint32_t iopte, pa, tmppte;
+    uint32_t iopte;
 
     iopte = s->regs[1] << 4;
     addr &= ~s->iostart;
     iopte += (addr >> (PAGE_SHIFT - 2)) & ~3;
-    pa = ldl_phys(iopte);
+    return ldl_phys(iopte);
+}
+
+static uint32_t iommu_translate_pa(IOMMUState *s, uint32_t addr, uint32_t pa)
+{
+    uint32_t tmppte;
+
     tmppte = pa;
     pa = ((pa & IOPTE_PAGE) << 4) + (addr & PAGE_MASK);
-    DPRINTF("xlate dva %x => pa %x (iopte[%x] = %x)\n", addr, pa, iopte, tmppte);
+    DPRINTF("xlate dva %x => pa %x (iopte = %x)\n", addr, pa, tmppte);
     return pa;
 }
 
+void sparc_iommu_memory_rw(void *opaque, target_phys_addr_t addr,
+                           uint8_t *buf, int len, int is_write)
+{
+    int l, flags;
+    target_ulong page, phys_addr;
+
+    while (len > 0) {
+        page = addr & TARGET_PAGE_MASK;
+        l = (page + TARGET_PAGE_SIZE) - addr;
+        if (l > len)
+            l = len;
+        flags = iommu_page_get_flags(opaque, page);
+        if (!(flags & IOPTE_VALID))
+            return;
+        phys_addr = iommu_translate_pa(opaque, addr, flags);
+        if (is_write) {
+            if (!(flags & IOPTE_WRITE))
+                return;
+            cpu_physical_memory_write(phys_addr, buf, len);
+        } else {
+            cpu_physical_memory_read(phys_addr, buf, len);
+        }
+        len -= l;
+        buf += l;
+        addr += l;
+    }
+}
+
 static void iommu_save(QEMUFile *f, void *opaque)
 {
     IOMMUState *s = opaque;
diff --git a/tools/ioemu/hw/isa_mmio.c b/tools/ioemu/hw/isa_mmio.c
new file mode 100644 (file)
index 0000000..070f6f5
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Memory mapped access to ISA IO space.
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "vl.h"
+
+static void isa_mmio_writeb (void *opaque, target_phys_addr_t addr,
+                                  uint32_t val)
+{
+    cpu_outb(NULL, addr & 0xffff, val);
+}
+
+static void isa_mmio_writew (void *opaque, target_phys_addr_t addr,
+                                  uint32_t val)
+{
+#ifdef TARGET_WORDS_BIGENDIAN
+    val = bswap16(val);
+#endif
+    cpu_outw(NULL, addr & 0xffff, val);
+}
+
+static void isa_mmio_writel (void *opaque, target_phys_addr_t addr,
+                                uint32_t val)
+{
+#ifdef TARGET_WORDS_BIGENDIAN
+    val = bswap32(val);
+#endif
+    cpu_outl(NULL, addr & 0xffff, val);
+}
+
+static uint32_t isa_mmio_readb (void *opaque, target_phys_addr_t addr)
+{
+    uint32_t val;
+
+    val = cpu_inb(NULL, addr & 0xffff);
+    return val;
+}
+
+static uint32_t isa_mmio_readw (void *opaque, target_phys_addr_t addr)
+{
+    uint32_t val;
+
+    val = cpu_inw(NULL, addr & 0xffff);
+#ifdef TARGET_WORDS_BIGENDIAN
+    val = bswap16(val);
+#endif
+    return val;
+}
+
+static uint32_t isa_mmio_readl (void *opaque, target_phys_addr_t addr)
+{
+    uint32_t val;
+
+    val = cpu_inl(NULL, addr & 0xffff);
+#ifdef TARGET_WORDS_BIGENDIAN
+    val = bswap32(val);
+#endif
+    return val;
+}
+
+static CPUWriteMemoryFunc *isa_mmio_write[] = {
+    &isa_mmio_writeb,
+    &isa_mmio_writew,
+    &isa_mmio_writel,
+};
+
+static CPUReadMemoryFunc *isa_mmio_read[] = {
+    &isa_mmio_readb,
+    &isa_mmio_readw,
+    &isa_mmio_readl,
+};
+
+static int isa_mmio_iomemtype = 0;
+
+void isa_mmio_init(target_phys_addr_t base, target_phys_addr_t size)
+{
+    if (!isa_mmio_iomemtype) {
+        isa_mmio_iomemtype = cpu_register_io_memory(0, isa_mmio_read,
+                                                    isa_mmio_write, NULL);
+    }
+    cpu_register_physical_memory(base, size, isa_mmio_iomemtype);
+}
diff --git a/tools/ioemu/hw/lance.c b/tools/ioemu/hw/lance.c
deleted file mode 100644 (file)
index d167937..0000000
+++ /dev/null
@@ -1,462 +0,0 @@
-/*
- * QEMU Lance emulation
- * 
- * Copyright (c) 2003-2005 Fabrice Bellard
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "vl.h"
-
-/* debug LANCE card */
-//#define DEBUG_LANCE
-
-#ifdef DEBUG_LANCE
-#define DPRINTF(fmt, args...) \
-do { printf("LANCE: " fmt , ##args); } while (0)
-#else
-#define DPRINTF(fmt, args...)
-#endif
-
-#ifndef LANCE_LOG_TX_BUFFERS
-#define LANCE_LOG_TX_BUFFERS 4
-#define LANCE_LOG_RX_BUFFERS 4
-#endif
-
-#define LE_CSR0 0
-#define LE_CSR1 1
-#define LE_CSR2 2
-#define LE_CSR3 3
-#define LE_NREGS (LE_CSR3 + 1)
-#define LE_MAXREG LE_CSR3
-
-#define LE_RDP  0
-#define LE_RAP  1
-
-#define LE_MO_PROM      0x8000  /* Enable promiscuous mode */
-
-#define        LE_C0_ERR       0x8000  /* Error: set if BAB, SQE, MISS or ME is set */
-#define        LE_C0_BABL      0x4000  /* BAB:  Babble: tx timeout. */
-#define        LE_C0_CERR      0x2000  /* SQE:  Signal quality error */
-#define        LE_C0_MISS      0x1000  /* MISS: Missed a packet */
-#define        LE_C0_MERR      0x0800  /* ME:   Memory error */
-#define        LE_C0_RINT      0x0400  /* Received interrupt */
-#define        LE_C0_TINT      0x0200  /* Transmitter Interrupt */
-#define        LE_C0_IDON      0x0100  /* IFIN: Init finished. */
-#define        LE_C0_INTR      0x0080  /* Interrupt or error */
-#define        LE_C0_INEA      0x0040  /* Interrupt enable */
-#define        LE_C0_RXON      0x0020  /* Receiver on */
-#define        LE_C0_TXON      0x0010  /* Transmitter on */
-#define        LE_C0_TDMD      0x0008  /* Transmitter demand */
-#define        LE_C0_STOP      0x0004  /* Stop the card */
-#define        LE_C0_STRT      0x0002  /* Start the card */
-#define        LE_C0_INIT      0x0001  /* Init the card */
-
-#define        LE_C3_BSWP      0x4     /* SWAP */
-#define        LE_C3_ACON      0x2     /* ALE Control */
-#define        LE_C3_BCON      0x1     /* Byte control */
-
-/* Receive message descriptor 1 */
-#define LE_R1_OWN       0x80    /* Who owns the entry */
-#define LE_R1_ERR       0x40    /* Error: if FRA, OFL, CRC or BUF is set */
-#define LE_R1_FRA       0x20    /* FRA: Frame error */
-#define LE_R1_OFL       0x10    /* OFL: Frame overflow */
-#define LE_R1_CRC       0x08    /* CRC error */
-#define LE_R1_BUF       0x04    /* BUF: Buffer error */
-#define LE_R1_SOP       0x02    /* Start of packet */
-#define LE_R1_EOP       0x01    /* End of packet */
-#define LE_R1_POK       0x03    /* Packet is complete: SOP + EOP */
-
-#define LE_T1_OWN       0x80    /* Lance owns the packet */
-#define LE_T1_ERR       0x40    /* Error summary */
-#define LE_T1_EMORE     0x10    /* Error: more than one retry needed */
-#define LE_T1_EONE      0x08    /* Error: one retry needed */
-#define LE_T1_EDEF      0x04    /* Error: deferred */
-#define LE_T1_SOP       0x02    /* Start of packet */
-#define LE_T1_EOP       0x01    /* End of packet */
-#define LE_T1_POK      0x03    /* Packet is complete: SOP + EOP */
-
-#define LE_T3_BUF       0x8000  /* Buffer error */
-#define LE_T3_UFL       0x4000  /* Error underflow */
-#define LE_T3_LCOL      0x1000  /* Error late collision */
-#define LE_T3_CLOS      0x0800  /* Error carrier loss */
-#define LE_T3_RTY       0x0400  /* Error retry */
-#define LE_T3_TDR       0x03ff  /* Time Domain Reflectometry counter */
-
-#define TX_RING_SIZE                   (1 << (LANCE_LOG_TX_BUFFERS))
-#define TX_RING_MOD_MASK               (TX_RING_SIZE - 1)
-#define TX_RING_LEN_BITS               ((LANCE_LOG_TX_BUFFERS) << 29)
-
-#define RX_RING_SIZE                   (1 << (LANCE_LOG_RX_BUFFERS))
-#define RX_RING_MOD_MASK               (RX_RING_SIZE - 1)
-#define RX_RING_LEN_BITS               ((LANCE_LOG_RX_BUFFERS) << 29)
-
-#define PKT_BUF_SZ             1544
-#define RX_BUFF_SIZE            PKT_BUF_SZ
-#define TX_BUFF_SIZE            PKT_BUF_SZ
-
-struct lance_rx_desc {
-       unsigned short rmd0;        /* low address of packet */
-       unsigned char  rmd1_bits;   /* descriptor bits */
-       unsigned char  rmd1_hadr;   /* high address of packet */
-       short    length;            /* This length is 2s complement (negative)!
-                                    * Buffer length
-                                    */
-       unsigned short mblength;    /* This is the actual number of bytes received */
-};
-
-struct lance_tx_desc {
-       unsigned short tmd0;        /* low address of packet */
-       unsigned char  tmd1_bits;   /* descriptor bits */
-       unsigned char  tmd1_hadr;   /* high address of packet */
-       short length;               /* Length is 2s complement (negative)! */
-       unsigned short misc;
-};
-
-/* The LANCE initialization block, described in databook. */
-/* On the Sparc, this block should be on a DMA region     */
-struct lance_init_block {
-       unsigned short mode;            /* Pre-set mode (reg. 15) */
-       unsigned char phys_addr[6];     /* Physical ethernet address */
-       unsigned filter[2];             /* Multicast filter. */
-
-       /* Receive and transmit ring base, along with extra bits. */
-       unsigned short rx_ptr;          /* receive descriptor addr */
-       unsigned short rx_len;          /* receive len and high addr */
-       unsigned short tx_ptr;          /* transmit descriptor addr */
-       unsigned short tx_len;          /* transmit len and high addr */
-    
-       /* The Tx and Rx ring entries must aligned on 8-byte boundaries. */
-       struct lance_rx_desc brx_ring[RX_RING_SIZE];
-       struct lance_tx_desc btx_ring[TX_RING_SIZE];
-    
-       char   tx_buf [TX_RING_SIZE][TX_BUFF_SIZE];
-       char   pad[2];                  /* align rx_buf for copy_and_sum(). */
-       char   rx_buf [RX_RING_SIZE][RX_BUFF_SIZE];
-};
-
-#define LEDMA_REGS 4
-#define LEDMA_MAXADDR (LEDMA_REGS * 4 - 1)
-
-typedef struct LANCEState {
-    VLANClientState *vc;
-    uint8_t macaddr[6]; /* init mac address */
-    uint32_t leptr;
-    uint16_t addr;
-    uint16_t regs[LE_NREGS];
-    uint8_t phys[6]; /* mac address */
-    int irq;
-    unsigned int rxptr, txptr;
-    uint32_t ledmaregs[LEDMA_REGS];
-} LANCEState;
-
-static void lance_send(void *opaque);
-
-static void lance_reset(void *opaque)
-{
-    LANCEState *s = opaque;
-    memcpy(s->phys, s->macaddr, 6);
-    s->rxptr = 0;
-    s->txptr = 0;
-    memset(s->regs, 0, LE_NREGS * 2);
-    s->regs[LE_CSR0] = LE_C0_STOP;
-    memset(s->ledmaregs, 0, LEDMA_REGS * 4);
-}
-
-static uint32_t lance_mem_readw(void *opaque, target_phys_addr_t addr)
-{
-    LANCEState *s = opaque;
-    uint32_t saddr;
-
-    saddr = addr & LE_MAXREG;
-    switch (saddr >> 1) {
-    case LE_RDP:
-       DPRINTF("read dreg[%d] = %4.4x\n", s->addr, s->regs[s->addr]);
-       return s->regs[s->addr];
-    case LE_RAP:
-       DPRINTF("read areg = %4.4x\n", s->addr);
-       return s->addr;
-    default:
-       DPRINTF("read unknown(%d)\n", saddr>>1);
-       break;
-    }
-    return 0;
-}
-
-static void lance_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-    LANCEState *s = opaque;
-    uint32_t saddr;
-    uint16_t reg;
-
-    saddr = addr & LE_MAXREG;
-    switch (saddr >> 1) {
-    case LE_RDP:
-       DPRINTF("write dreg[%d] = %4.4x\n", s->addr, val);
-       switch(s->addr) {
-       case LE_CSR0:
-           if (val & LE_C0_STOP) {
-               s->regs[LE_CSR0] = LE_C0_STOP;
-               break;
-           }
-
-           reg = s->regs[LE_CSR0];
-
-           // 1 = clear for some bits
-           reg &= ~(val & 0x7f00);
-
-           // generated bits
-           reg &= ~(LE_C0_ERR | LE_C0_INTR);
-           if (reg & 0x7100)
-               reg |= LE_C0_ERR;
-           if (reg & 0x7f00)
-               reg |= LE_C0_INTR;
-
-           // direct bit
-           reg &= ~LE_C0_INEA;
-           reg |= val & LE_C0_INEA;
-
-           // exclusive bits
-           if (val & LE_C0_INIT) {
-               reg |= LE_C0_IDON | LE_C0_INIT;
-               reg &= ~LE_C0_STOP;
-           }
-           else if (val & LE_C0_STRT) {
-               reg |= LE_C0_STRT | LE_C0_RXON | LE_C0_TXON;
-               reg &= ~LE_C0_STOP;
-           }
-
-           s->regs[LE_CSR0] = reg;
-           break;
-       case LE_CSR1:
-           s->leptr = (s->leptr & 0xffff0000) | (val & 0xffff);
-           s->regs[s->addr] = val;
-           break;
-       case LE_CSR2:
-           s->leptr = (s->leptr & 0xffff) | ((val & 0xffff) << 16);
-           s->regs[s->addr] = val;
-           break;
-       case LE_CSR3:
-           s->regs[s->addr] = val;
-           break;
-       }
-       break;
-    case LE_RAP:
-       DPRINTF("write areg = %4.4x\n", val);
-       if (val < LE_NREGS)
-           s->addr = val;
-       break;
-    default:
-       DPRINTF("write unknown(%d) = %4.4x\n", saddr>>1, val);
-       break;
-    }
-    lance_send(s);
-}
-
-static CPUReadMemoryFunc *lance_mem_read[3] = {
-    lance_mem_readw,
-    lance_mem_readw,
-    lance_mem_readw,
-};
-
-static CPUWriteMemoryFunc *lance_mem_write[3] = {
-    lance_mem_writew,
-    lance_mem_writew,
-    lance_mem_writew,
-};
-
-
-#define MIN_BUF_SIZE 60
-
-static int lance_can_receive(void *opaque)
-{
-    return 1;
-}
-
-static void lance_receive(void *opaque, const uint8_t *buf, int size)
-{
-    LANCEState *s = opaque;
-    uint32_t dmaptr = s->leptr + s->ledmaregs[3];
-    struct lance_init_block *ib;
-    unsigned int i, old_rxptr;
-    uint16_t temp16;
-    uint8_t temp8;
-
-    DPRINTF("receive size %d\n", size);
-    if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP)
-       return;
-
-    ib = (void *) iommu_translate(dmaptr);
-
-    old_rxptr = s->rxptr;
-    for (i = s->rxptr; i != ((old_rxptr - 1) & RX_RING_MOD_MASK); i = (i + 1) & RX_RING_MOD_MASK) {
-       cpu_physical_memory_read((uint32_t)&ib->brx_ring[i].rmd1_bits, (void *) &temp8, 1);
-       if (temp8 == (LE_R1_OWN)) {
-           s->rxptr = (s->rxptr + 1) & RX_RING_MOD_MASK;
-           temp16 = size + 4;
-           bswap16s(&temp16);
-           cpu_physical_memory_write((uint32_t)&ib->brx_ring[i].mblength, (void *) &temp16, 2);
-           cpu_physical_memory_write((uint32_t)&ib->rx_buf[i], buf, size);
-           temp8 = LE_R1_POK;
-           cpu_physical_memory_write((uint32_t)&ib->brx_ring[i].rmd1_bits, (void *) &temp8, 1);
-           s->regs[LE_CSR0] |= LE_C0_RINT | LE_C0_INTR;
-           if (s->regs[LE_CSR0] & LE_C0_INEA)
-               pic_set_irq(s->irq, 1);
-           DPRINTF("got packet, len %d\n", size);
-           return;
-       }
-    }
-}
-
-static void lance_send(void *opaque)
-{
-    LANCEState *s = opaque;
-    uint32_t dmaptr = s->leptr + s->ledmaregs[3];
-    struct lance_init_block *ib;
-    unsigned int i, old_txptr;
-    uint16_t temp16;
-    uint8_t temp8;
-    char pkt_buf[PKT_BUF_SZ];
-
-    DPRINTF("sending packet? (csr0 %4.4x)\n", s->regs[LE_CSR0]);
-    if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP)
-       return;
-
-    ib = (void *) iommu_translate(dmaptr);
-
-    DPRINTF("sending packet? (dmaptr %8.8x) (ib %p) (btx_ring %p)\n", dmaptr, ib, &ib->btx_ring);
-    old_txptr = s->txptr;
-    for (i = s->txptr; i != ((old_txptr - 1) & TX_RING_MOD_MASK); i = (i + 1) & TX_RING_MOD_MASK) {
-       cpu_physical_memory_read((uint32_t)&ib->btx_ring[i].tmd1_bits, (void *) &temp8, 1);
-       if (temp8 == (LE_T1_POK|LE_T1_OWN)) {
-           cpu_physical_memory_read((uint32_t)&ib->btx_ring[i].length, (void *) &temp16, 2);
-           bswap16s(&temp16);
-           temp16 = (~temp16) + 1;
-           cpu_physical_memory_read((uint32_t)&ib->tx_buf[i], pkt_buf, temp16);
-           DPRINTF("sending packet, len %d\n", temp16);
-           qemu_send_packet(s->vc, pkt_buf, temp16);
-           temp8 = LE_T1_POK;
-           cpu_physical_memory_write((uint32_t)&ib->btx_ring[i].tmd1_bits, (void *) &temp8, 1);
-           s->txptr = (s->txptr + 1) & TX_RING_MOD_MASK;
-           s->regs[LE_CSR0] |= LE_C0_TINT | LE_C0_INTR;
-       }
-    }
-    if ((s->regs[LE_CSR0] & LE_C0_INTR) && (s->regs[LE_CSR0] & LE_C0_INEA))
-       pic_set_irq(s->irq, 1);
-}
-
-static uint32_t ledma_mem_readl(void *opaque, target_phys_addr_t addr)
-{
-    LANCEState *s = opaque;
-    uint32_t saddr;
-
-    saddr = (addr & LEDMA_MAXADDR) >> 2;
-    return s->ledmaregs[saddr];
-}
-
-static void ledma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-    LANCEState *s = opaque;
-    uint32_t saddr;
-
-    saddr = (addr & LEDMA_MAXADDR) >> 2;
-    s->ledmaregs[saddr] = val;
-}
-
-static CPUReadMemoryFunc *ledma_mem_read[3] = {
-    ledma_mem_readl,
-    ledma_mem_readl,
-    ledma_mem_readl,
-};
-
-static CPUWriteMemoryFunc *ledma_mem_write[3] = {
-    ledma_mem_writel,
-    ledma_mem_writel,
-    ledma_mem_writel,
-};
-
-static void lance_save(QEMUFile *f, void *opaque)
-{
-    LANCEState *s = opaque;
-    int i;
-    
-    qemu_put_be32s(f, &s->leptr);
-    qemu_put_be16s(f, &s->addr);
-    for (i = 0; i < LE_NREGS; i ++)
-       qemu_put_be16s(f, &s->regs[i]);
-    qemu_put_buffer(f, s->phys, 6);
-    qemu_put_be32s(f, &s->irq);
-    for (i = 0; i < LEDMA_REGS; i ++)
-       qemu_put_be32s(f, &s->ledmaregs[i]);
-}
-
-static int lance_load(QEMUFile *f, void *opaque, int version_id)
-{
-    LANCEState *s = opaque;
-    int i;
-    
-    if (version_id != 1)
-        return -EINVAL;
-
-    qemu_get_be32s(f, &s->leptr);
-    qemu_get_be16s(f, &s->addr);
-    for (i = 0; i < LE_NREGS; i ++)
-       qemu_get_be16s(f, &s->regs[i]);
-    qemu_get_buffer(f, s->phys, 6);
-    qemu_get_be32s(f, &s->irq);
-    for (i = 0; i < LEDMA_REGS; i ++)
-       qemu_get_be32s(f, &s->ledmaregs[i]);
-    return 0;
-}
-
-void lance_init(NICInfo *nd, int irq, uint32_t leaddr, uint32_t ledaddr)
-{
-    LANCEState *s;
-    int lance_io_memory, ledma_io_memory;
-
-    s = qemu_mallocz(sizeof(LANCEState));
-    if (!s)
-        return;
-
-    s->irq = irq;
-
-    lance_io_memory = cpu_register_io_memory(0, lance_mem_read, lance_mem_write, s);
-    cpu_register_physical_memory(leaddr, 4, lance_io_memory);
-
-    ledma_io_memory = cpu_register_io_memory(0, ledma_mem_read, ledma_mem_write, s);
-    cpu_register_physical_memory(ledaddr, 16, ledma_io_memory);
-
-    memcpy(s->macaddr, nd->macaddr, 6);
-
-    lance_reset(s);
-
-    s->vc = qemu_new_vlan_client(nd->vlan, lance_receive, lance_can_receive, s);
-
-    snprintf(s->vc->info_str, sizeof(s->vc->info_str),
-             "lance macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
-             s->macaddr[0],
-             s->macaddr[1],
-             s->macaddr[2],
-             s->macaddr[3],
-             s->macaddr[4],
-             s->macaddr[5]);
-
-    register_savevm("lance", leaddr, 1, lance_save, lance_load, s);
-    qemu_register_reset(lance_reset, s);
-}
-
index 908e856e706936f55e8cba99ea44a4bc9552946a..7aa70bfa70d745b4d6b95748af36c0866794ed6c 100644 (file)
 #define DPRINTF(fmt, args...) \
 do { printf("lsi_scsi: " fmt , ##args); } while (0)
 #define BADF(fmt, args...) \
-do { fprintf(stderr, "lsi_scsi: " fmt , ##args); exit(1);} while (0)
+do { fprintf(stderr, "lsi_scsi: error: " fmt , ##args); exit(1);} while (0)
 #else
 #define DPRINTF(fmt, args...) do {} while(0)
 #define BADF(fmt, args...) \
-do { fprintf(stderr, "lsi_scsi: " fmt , ##args); } while (0)
+do { fprintf(stderr, "lsi_scsi: error: " fmt , ##args);} while (0)
 #endif
 
 #define LSI_SCNTL0_TRG    0x01
@@ -152,21 +152,46 @@ do { fprintf(stderr, "lsi_scsi: " fmt , ##args); } while (0)
 /* The HBA is ID 7, so for simplicitly limit to 7 devices.  */
 #define LSI_MAX_DEVS      7
 
+/* Maximum length of MSG IN data.  */
+#define LSI_MAX_MSGIN_LEN 8
+
+/* Flag set if this is a tagged command.  */
+#define LSI_TAG_VALID     (1 << 16)
+
+typedef struct {
+    uint32_t tag;
+    uint32_t pending;
+    int out;
+} lsi_queue;
+
 typedef struct {
     PCIDevice pci_dev;
     int mmio_io_addr;
     int ram_io_addr;
     uint32_t script_ram_base;
-    uint32_t data_len;
 
     int carry; /* ??? Should this be an a visible register somewhere?  */
     int sense;
-    uint8_t msg;
-    /* Nonzero if a Wait Reselect instruction has been issued.  */
+    /* Action to take at the end of a MSG IN phase.
+       0 = COMMAND, 1 = disconect, 2 = DATA OUT, 3 = DATA IN.  */
+    int msg_action;
+    int msg_len;
+    uint8_t msg[LSI_MAX_MSGIN_LEN];
+    /* 0 if SCRIPTS are running or stopped.
+     * 1 if a Wait Reselect instruction has been issued.
+     * 2 if processing DMA from lsi_execute_script.
+     * 3 if a DMA operation is in progress.  */
     int waiting;
     SCSIDevice *scsi_dev[LSI_MAX_DEVS];
     SCSIDevice *current_dev;
     int current_lun;
+    /* The tag is a combination of the device ID and the SCSI tag.  */
+    uint32_t current_tag;
+    uint32_t current_dma_len;
+    uint8_t *dma_buf;
+    lsi_queue *queue;
+    int queue_len;
+    int active_commands;
 
     uint32_t dsa;
     uint32_t temp;
@@ -203,10 +228,12 @@ typedef struct {
     uint8_t sxfer;
     uint8_t socl;
     uint8_t sdid;
+    uint8_t ssid;
     uint8_t sfbr;
     uint8_t stest1;
     uint8_t stest2;
     uint8_t stest3;
+    uint8_t sidl;
     uint8_t stime0;
     uint8_t respid0;
     uint8_t respid1;
@@ -274,6 +301,7 @@ static void lsi_soft_reset(LSIState *s)
     s->stest1 = 0;
     s->stest2 = 0;
     s->stest3 = 0;
+    s->sidl = 0;
     s->stime0 = 0;
     s->respid0 = 0x80;
     s->respid1 = 0;
@@ -295,6 +323,7 @@ static void lsi_soft_reset(LSIState *s)
 
 static uint8_t lsi_reg_readb(LSIState *s, int offset);
 static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val);
+static void lsi_execute_script(LSIState *s);
 
 static inline uint32_t read_dword(LSIState *s, uint32_t addr)
 {
@@ -402,45 +431,197 @@ static void lsi_bad_phase(LSIState *s, int out, int new_phase)
     lsi_set_phase(s, new_phase);
 }
 
+
+/* Resume SCRIPTS execution after a DMA operation.  */
+static void lsi_resume_script(LSIState *s)
+{
+    if (s->waiting != 2) {
+        s->waiting = 0;
+        lsi_execute_script(s);
+    } else {
+        s->waiting = 0;
+    }
+}
+
+/* Initiate a SCSI layer data transfer.  */
 static void lsi_do_dma(LSIState *s, int out)
 {
-    uint8_t buf[TARGET_PAGE_SIZE];
-    uint32_t addr;
     uint32_t count;
-    int n;
+    uint32_t addr;
 
-    count = s->dbc;
-    addr = s->dnad;
-    DPRINTF("DMA %s addr=0x%08x len=%d avail=%d\n", out ? "out" : "in",
-            addr, count, s->data_len);
-    /* ??? Too long transfers are truncated. Don't know if this is the
-       correct behavior.  */
-    if (count > s->data_len) {
-        /* If the DMA length is greater then the device data length then
-           a phase mismatch will occur.  */
-        count = s->data_len;
-        s->dbc = count;
-        lsi_bad_phase(s, out, PHASE_ST);
+    if (!s->current_dma_len) {
+        /* Wait until data is available.  */
+        DPRINTF("DMA no data available\n");
+        return;
     }
 
+    count = s->dbc;
+    if (count > s->current_dma_len)
+        count = s->current_dma_len;
+    DPRINTF("DMA addr=0x%08x len=%d\n", s->dnad, count);
+
+    addr = s->dnad;
     s->csbc += count;
+    s->dnad += count;
+    s->dbc -= count;
+
+    if (s->dma_buf == NULL) {
+        s->dma_buf = scsi_get_buf(s->current_dev, s->current_tag);
+    }
 
     /* ??? Set SFBR to first data byte.  */
-    while (count) {
-        n = (count > TARGET_PAGE_SIZE) ? TARGET_PAGE_SIZE : count;
+    if (out) {
+        cpu_physical_memory_read(addr, s->dma_buf, count);
+    } else {
+        cpu_physical_memory_write(addr, s->dma_buf, count);
+    }
+    s->current_dma_len -= count;
+    if (s->current_dma_len == 0) {
+        s->dma_buf = NULL;
         if (out) {
-            cpu_physical_memory_read(addr, buf, n);
-            scsi_write_data(s->current_dev, buf, n);
+            /* Write the data.  */
+            scsi_write_data(s->current_dev, s->current_tag);
         } else {
-            scsi_read_data(s->current_dev, buf, n);
-            cpu_physical_memory_write(addr, buf, n);
+            /* Request any remaining data.  */
+            scsi_read_data(s->current_dev, s->current_tag);
         }
-        addr += n;
-        count -= n;
+    } else {
+        s->dma_buf += count;
+        lsi_resume_script(s);
     }
 }
 
 
+/* Add a command to the queue.  */
+static void lsi_queue_command(LSIState *s)
+{
+    lsi_queue *p;
+
+    DPRINTF("Queueing tag=0x%x\n", s->current_tag);
+    if (s->queue_len == s->active_commands) {
+        s->queue_len++;
+        s->queue = realloc(s->queue, s->queue_len * sizeof(lsi_queue));
+    }
+    p = &s->queue[s->active_commands++];
+    p->tag = s->current_tag;
+    p->pending = 0;
+    p->out = (s->sstat1 & PHASE_MASK) == PHASE_DO;
+}
+
+/* Queue a byte for a MSG IN phase.  */
+static void lsi_add_msg_byte(LSIState *s, uint8_t data)
+{
+    if (s->msg_len >= LSI_MAX_MSGIN_LEN) {
+        BADF("MSG IN data too long\n");
+    } else {
+        DPRINTF("MSG IN 0x%02x\n", data);
+        s->msg[s->msg_len++] = data;
+    }
+}
+
+/* Perform reselection to continue a command.  */
+static void lsi_reselect(LSIState *s, uint32_t tag)
+{
+    lsi_queue *p;
+    int n;
+    int id;
+
+    p = NULL;
+    for (n = 0; n < s->active_commands; n++) {
+        p = &s->queue[n];
+        if (p->tag == tag)
+            break;
+    }
+    if (n == s->active_commands) {
+        BADF("Reselected non-existant command tag=0x%x\n", tag);
+        return;
+    }
+    id = (tag >> 8) & 0xf;
+    s->ssid = id | 0x80;
+    DPRINTF("Reselected target %d\n", id);
+    s->current_dev = s->scsi_dev[id];
+    s->current_tag = tag;
+    s->scntl1 |= LSI_SCNTL1_CON;
+    lsi_set_phase(s, PHASE_MI);
+    s->msg_action = p->out ? 2 : 3;
+    s->current_dma_len = p->pending;
+    s->dma_buf = NULL;
+    lsi_add_msg_byte(s, 0x80);
+    if (s->current_tag & LSI_TAG_VALID) {
+        lsi_add_msg_byte(s, 0x20);
+        lsi_add_msg_byte(s, tag & 0xff);
+    }
+
+    s->active_commands--;
+    if (n != s->active_commands) {
+        s->queue[n] = s->queue[s->active_commands];
+    }
+}
+
+/* Record that data is available for a queued command.  Returns zero if
+   the device was reselected, nonzero if the IO is deferred.  */
+static int lsi_queue_tag(LSIState *s, uint32_t tag, uint32_t arg)
+{
+    lsi_queue *p;
+    int i;
+    for (i = 0; i < s->active_commands; i++) {
+        p = &s->queue[i];
+        if (p->tag == tag) {
+            if (p->pending) {
+                BADF("Multiple IO pending for tag %d\n", tag);
+            }
+            p->pending = arg;
+            if (s->waiting == 1) {
+                /* Reselect device.  */
+                lsi_reselect(s, tag);
+                return 0;
+            } else {
+               DPRINTF("Queueing IO tag=0x%x\n", tag);
+                p->pending = arg;
+                return 1;
+            }
+        }
+    }
+    BADF("IO with unknown tag %d\n", tag);
+    return 1;
+}
+
+/* Callback to indicate that the SCSI layer has completed a transfer.  */
+static void lsi_command_complete(void *opaque, int reason, uint32_t tag,
+                                 uint32_t arg)
+{
+    LSIState *s = (LSIState *)opaque;
+    int out;
+
+    out = (s->sstat1 & PHASE_MASK) == PHASE_DO;
+    if (reason == SCSI_REASON_DONE) {
+        DPRINTF("Command complete sense=%d\n", (int)arg);
+        s->sense = arg;
+        if (s->waiting && s->dbc != 0) {
+            /* Raise phase mismatch for short transfers.  */
+            lsi_bad_phase(s, out, PHASE_ST);
+        } else {
+            lsi_set_phase(s, PHASE_ST);
+        }
+        lsi_resume_script(s);
+        return;
+    }
+
+    if (s->waiting == 1 || tag != s->current_tag) {
+        if (lsi_queue_tag(s, tag, arg))
+            return;
+    }
+    DPRINTF("Data ready tag=0x%x len=%d\n", tag, arg);
+    s->current_dma_len = arg;
+    if (!s->waiting)
+        return;
+    if (s->waiting == 1 || s->dbc == 0) {
+        lsi_resume_script(s);
+    } else {
+        lsi_do_dma(s, out);
+    }
+}
+
 static void lsi_do_command(LSIState *s)
 {
     uint8_t buf[16];
@@ -451,36 +632,37 @@ static void lsi_do_command(LSIState *s)
         s->dbc = 16;
     cpu_physical_memory_read(s->dnad, buf, s->dbc);
     s->sfbr = buf[0];
-    n = scsi_send_command(s->current_dev, 0, buf, s->current_lun);
+    n = scsi_send_command(s->current_dev, s->current_tag, buf, s->current_lun);
     if (n > 0) {
-        s->data_len = n;
         lsi_set_phase(s, PHASE_DI);
+        scsi_read_data(s->current_dev, s->current_tag);
     } else if (n < 0) {
-        s->data_len = -n;
         lsi_set_phase(s, PHASE_DO);
+        scsi_write_data(s->current_dev, s->current_tag);
+    }
+    if (n && s->current_dma_len == 0) {
+        /* Command did not complete immediately so disconnect.  */
+        lsi_add_msg_byte(s, 2); /* SAVE DATA POINTER */
+        lsi_add_msg_byte(s, 4); /* DISCONNECT */
+        lsi_set_phase(s, PHASE_MI);
+        s->msg_action = 1;
+        lsi_queue_command(s);
     }
-}
-
-static void lsi_command_complete(void *opaque, uint32_t tag, int sense)
-{
-    LSIState *s = (LSIState *)opaque;
-
-    DPRINTF("Command complete sense=%d\n", sense);
-    s->sense = sense;
-    lsi_set_phase(s, PHASE_ST);
 }
 
 static void lsi_do_status(LSIState *s)
 {
+    uint8_t sense;
     DPRINTF("Get status len=%d sense=%d\n", s->dbc, s->sense);
     if (s->dbc != 1)
         BADF("Bad Status move\n");
     s->dbc = 1;
-    s->msg = s->sense;
-    cpu_physical_memory_write(s->dnad, &s->msg, 1);
-    s->sfbr = s->msg;
+    sense = s->sense;
+    s->sfbr = sense;
+    cpu_physical_memory_write(s->dnad, &sense, 1);
     lsi_set_phase(s, PHASE_MI);
-    s->msg = 0; /* COMMAND COMPLETE */
+    s->msg_action = 1;
+    lsi_add_msg_byte(s, 0); /* COMMAND COMPLETE */
 }
 
 static void lsi_disconnect(LSIState *s)
@@ -491,55 +673,114 @@ static void lsi_disconnect(LSIState *s)
 
 static void lsi_do_msgin(LSIState *s)
 {
-    DPRINTF("Message in len=%d\n", s->dbc);
-    s->dbc = 1;
-    s->sfbr = s->msg;
-    cpu_physical_memory_write(s->dnad, &s->msg, 1);
-    if (s->msg == 0) {
-        lsi_disconnect(s);
+    int len;
+    DPRINTF("Message in len=%d/%d\n", s->dbc, s->msg_len);
+    s->sfbr = s->msg[0];
+    len = s->msg_len;
+    if (len > s->dbc)
+        len = s->dbc;
+    cpu_physical_memory_write(s->dnad, s->msg, len);
+    /* Linux drivers rely on the last byte being in the SIDL.  */
+    s->sidl = s->msg[len - 1];
+    s->msg_len -= len;
+    if (s->msg_len) {
+        memmove(s->msg, s->msg + len, s->msg_len);
     } else {
         /* ??? Check if ATN (not yet implemented) is asserted and maybe
            switch to PHASE_MO.  */
-        lsi_set_phase(s, PHASE_CMD);
+        switch (s->msg_action) {
+        case 0:
+            lsi_set_phase(s, PHASE_CMD);
+            break;
+        case 1:
+            lsi_disconnect(s);
+            break;
+        case 2:
+            lsi_set_phase(s, PHASE_DO);
+            break;
+        case 3:
+            lsi_set_phase(s, PHASE_DI);
+            break;
+        default:
+            abort();
+        }
     }
 }
 
+/* Read the next byte during a MSGOUT phase.  */
+static uint8_t lsi_get_msgbyte(LSIState *s)
+{
+    uint8_t data;
+    cpu_physical_memory_read(s->dnad, &data, 1);
+    s->dnad++;
+    s->dbc--;
+    return data;
+}
+
 static void lsi_do_msgout(LSIState *s)
 {
     uint8_t msg;
+    int len;
 
     DPRINTF("MSG out len=%d\n", s->dbc);
-    if (s->dbc != 1) {
-        /* Multibyte messages not implemented.  */
-        s->msg = 7; /* MESSAGE REJECT */
-        //s->dbc = 1;
-        //lsi_bad_phase(s, 1, PHASE_MI);
-        lsi_set_phase(s, PHASE_MI);
-        return;
-    }
-    cpu_physical_memory_read(s->dnad, &msg, 1);
-    s->sfbr = msg;
-    s->dnad++;
-
-    switch (msg) {
-    case 0x00:
-        DPRINTF("Got Disconnect\n");
-        lsi_disconnect(s);
-        return;
-    case 0x08:
-        DPRINTF("Got No Operation\n");
-        lsi_set_phase(s, PHASE_CMD);
-        return;
-    }
-    if ((msg & 0x80) == 0) {
-        DPRINTF("Unimplemented message 0x%d\n", msg);
-        s->msg = 7; /* MESSAGE REJECT */
-        lsi_bad_phase(s, 1, PHASE_MI);
-        return;
+    while (s->dbc) {
+        msg = lsi_get_msgbyte(s);
+        s->sfbr = msg;
+
+        switch (msg) {
+        case 0x00:
+            DPRINTF("MSG: Disconnect\n");
+            lsi_disconnect(s);
+            break;
+        case 0x08:
+            DPRINTF("MSG: No Operation\n");
+            lsi_set_phase(s, PHASE_CMD);
+            break;
+        case 0x01:
+            len = lsi_get_msgbyte(s);
+            msg = lsi_get_msgbyte(s);
+            DPRINTF("Extended message 0x%x (len %d)\n", msg, len);
+            switch (msg) {
+            case 1:
+                DPRINTF("SDTR (ignored)\n");
+                s->dbc -= 2;
+                break;
+            case 3:
+                DPRINTF("WDTR (ignored)\n");
+                s->dbc -= 1;
+                break;
+            default:
+                goto bad;
+            }
+            break;
+        case 0x20: /* SIMPLE queue */
+            s->current_tag |= lsi_get_msgbyte(s) | LSI_TAG_VALID;
+            DPRINTF("SIMPLE queue tag=0x%x\n", s->current_tag & 0xff);
+            break;
+        case 0x21: /* HEAD of queue */
+            BADF("HEAD queue not implemented\n");
+            s->current_tag |= lsi_get_msgbyte(s) | LSI_TAG_VALID;
+            break;
+        case 0x22: /* ORDERED queue */
+            BADF("ORDERED queue not implemented\n");
+            s->current_tag |= lsi_get_msgbyte(s) | LSI_TAG_VALID;
+            break;
+        default:
+            if ((msg & 0x80) == 0) {
+                goto bad;
+            }
+            s->current_lun = msg & 7;
+            DPRINTF("Select LUN %d\n", s->current_lun);
+            lsi_set_phase(s, PHASE_CMD);
+            break;
+        }
     }
-    s->current_lun = msg & 7;
-    DPRINTF("Select LUN %d\n", s->current_lun);
-    lsi_set_phase(s, PHASE_CMD);
+    return;
+bad:
+    BADF("Unimplemented message 0x%02x\n", msg);
+    lsi_set_phase(s, PHASE_MI);
+    lsi_add_msg_byte(s, 7); /* MESSAGE REJECT */
+    s->msg_action = 0;
 }
 
 /* Sign extend a 24-bit value.  */
@@ -564,6 +805,23 @@ static void lsi_memcpy(LSIState *s, uint32_t dest, uint32_t src, int count)
     }
 }
 
+static void lsi_wait_reselect(LSIState *s)
+{
+    int i;
+    DPRINTF("Wait Reselect\n");
+    if (s->current_dma_len)
+        BADF("Reselect with pending DMA\n");
+    for (i = 0; i < s->active_commands; i++) {
+        if (s->queue[i].pending) {
+            lsi_reselect(s, s->queue[i].tag);
+            break;
+        }
+    }
+    if (s->current_dma_len == 0) {
+        s->waiting = 1;
+    }
+}
+
 static void lsi_execute_script(LSIState *s)
 {
     uint32_t insn;
@@ -608,10 +866,16 @@ again:
         s->dnad = addr;
         switch (s->sstat1 & 0x7) {
         case PHASE_DO:
+            s->waiting = 2;
             lsi_do_dma(s, 1);
+            if (s->waiting)
+                s->waiting = 3;
             break;
         case PHASE_DI:
+            s->waiting = 2;
             lsi_do_dma(s, 0);
+            if (s->waiting)
+                s->waiting = 3;
             break;
         case PHASE_CMD:
             lsi_do_command(s);
@@ -655,9 +919,13 @@ again:
             s->dnad = addr;
             switch (opcode) {
             case 0: /* Select */
+                s->sdid = id;
+                if (s->current_dma_len && (s->ssid & 0xf) == id) {
+                    DPRINTF("Already reselected by target %d\n", id);
+                    break;
+                }
                 s->sstat0 |= LSI_SSTAT0_WOA;
                 s->scntl1 &= ~LSI_SCNTL1_IARB;
-                s->sdid = id;
                 if (id >= LSI_MAX_DEVS || !s->scsi_dev[id]) {
                     DPRINTF("Selected absent target %d\n", id);
                     lsi_script_scsi_interrupt(s, 0, LSI_SIST1_STO);
@@ -670,6 +938,7 @@ again:
                    it only applies in low-level mode (unimplemented).
                 lsi_script_scsi_interrupt(s, LSI_SIST0_CMP, 0); */
                 s->current_dev = s->scsi_dev[id];
+                s->current_tag = id << 8;
                 s->scntl1 |= LSI_SCNTL1_CON;
                 if (insn & (1 << 3)) {
                     s->socl |= LSI_SOCL_ATN;
@@ -681,8 +950,7 @@ again:
                 s->scntl1 &= ~LSI_SCNTL1_CON;
                 break;
             case 2: /* Wait Reselect */
-                DPRINTF("Wait Reselect\n");
-                s->waiting = 1;
+                lsi_wait_reselect(s);
                 break;
             case 3: /* Set */
                 DPRINTF("Set%s%s%s%s\n",
@@ -731,9 +999,9 @@ again:
             data8 = (insn >> 8) & 0xff;
             opcode = (insn >> 27) & 7;
             operator = (insn >> 24) & 7;
-            DPRINTF("%s reg 0x%x %s data8 %d%s\n",
+            DPRINTF("%s reg 0x%x %s data8=0x%02x sfbr=0x%02x%s\n",
                     opcode_names[opcode - 5], reg,
-                    operator_names[operator], data8,
+                    operator_names[operator], data8, s->sfbr,
                     (insn & (1 << 23)) ? " SFBR" : "");
             op0 = op1 = 0;
             switch (opcode) {
@@ -899,8 +1167,9 @@ again:
             n = (insn & 7);
             reg = (insn >> 16) & 0xff;
             if (insn & (1 << 24)) {
-                DPRINTF("Load reg 0x%x size %d addr 0x%08x\n", reg, n, addr);
                 cpu_physical_memory_read(addr, data, n);
+                DPRINTF("Load reg 0x%x size %d addr 0x%08x = %08x\n", reg, n,
+                        addr, *(int *)data);
                 for (i = 0; i < n; i++) {
                     lsi_reg_writeb(s, reg + i, data[i]);
                 }
@@ -953,6 +1222,8 @@ static uint8_t lsi_reg_readb(LSIState *s, int offset)
         return s->sdid;
     case 0x07: /* GPREG0 */
         return 0x7f;
+    case 0xa: /* SSID */
+        return s->ssid;
     case 0xb: /* SBCL */
         /* ??? This is not correct. However it's (hopefully) only
            used for diagnostics, so should be ok.  */
@@ -1041,13 +1312,22 @@ static uint8_t lsi_reg_readb(LSIState *s, int offset)
         return s->stest2;
     case 0x4f: /* STEST3 */
         return s->stest3;
+    case 0x50: /* SIDL */
+        /* This is needed by the linux drivers.  We currently only update it
+           during the MSG IN phase.  */
+        return s->sidl;
     case 0x52: /* STEST4 */
         return 0xe0;
     case 0x56: /* CCNTL0 */
         return s->ccntl0;
     case 0x57: /* CCNTL1 */
         return s->ccntl1;
-    case 0x58: case 0x59: /* SBDL */
+    case 0x58: /* SBDL */
+        /* Some drivers peek at the data bus during the MSG IN phase.  */
+        if ((s->sstat1 & PHASE_MASK) == PHASE_MI)
+            return s->msg[0];
+        return 0;
+    case 0x59: /* SBDL high */
         return 0;
     CASE_GET_REG32(mmrs, 0xa0)
     CASE_GET_REG32(mmws, 0xa4)
@@ -1124,8 +1404,18 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
     case 0x05: /* SXFER */
         s->sxfer = val;
         break;
+    case 0x06: /* SDID */
+        if ((val & 0xf) != (s->ssid & 0xf))
+            BADF("Destination ID does not match SSID\n");
+        s->sdid = val & 0xf;
+        break;
     case 0x07: /* GPREG0 */
         break;
+    case 0x08: /* SFBR */
+        /* The CPU is not allowed to write to this register.  However the
+           SCRIPTS register move instructions are.  */
+        s->sfbr = val;
+        break;
     case 0x0c: case 0x0d: case 0x0e: case 0x0f:
         /* Linux writes to these readonly registers on startup.  */
         return;
@@ -1139,7 +1429,7 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
             s->istat0 &= ~LSI_ISTAT0_INTF;
             lsi_update_irq(s);
         }
-        if (s->waiting && val & LSI_ISTAT0_SIGP) {
+        if (s->waiting == 1 && val & LSI_ISTAT0_SIGP) {
             DPRINTF("Woken by SIGP\n");
             s->waiting = 0;
             s->dsp = s->dnad;
@@ -1536,7 +1826,7 @@ void lsi_scsi_attach(void *opaque, BlockDriverState *bd, int id)
         scsi_disk_destroy(s->scsi_dev[id]);
     }
     DPRINTF("Attaching block device %d\n", id);
-    s->scsi_dev[id] = scsi_disk_init(bd, lsi_command_complete, s);
+    s->scsi_dev[id] = scsi_disk_init(bd, 1, lsi_command_complete, s);
 }
 
 void *lsi_scsi_init(PCIBus *bus, int devfn)
@@ -1568,6 +1858,9 @@ void *lsi_scsi_init(PCIBus *bus, int devfn)
                            PCI_ADDRESS_SPACE_MEM, lsi_mmio_mapfunc);
     pci_register_io_region((struct PCIDevice *)s, 2, 0x2000,
                            PCI_ADDRESS_SPACE_MEM, lsi_ram_mapfunc);
+    s->queue = qemu_malloc(sizeof(lsi_queue));
+    s->queue_len = 1;
+    s->active_commands = 0;
 
     lsi_soft_reset(s);
 
index cf0f2c029ef84668851b9516c18889f6859b2640..4155c5ebf3c21e8c14d4391bf113dcce277d160a 100644 (file)
@@ -403,6 +403,30 @@ void rtc_set_date(RTCState *s, const struct tm *tm)
     rtc_copy_date(s);
 }
 
+/* PC cmos mappings */
+#define REG_IBM_CENTURY_BYTE        0x32
+#define REG_IBM_PS2_CENTURY_BYTE    0x37
+
+void rtc_set_date_from_host(RTCState *s)
+{
+    time_t ti;
+    struct tm *tm;
+    int val;
+
+    /* set the CMOS date */
+    time(&ti);
+    ti += timeoffset;
+    if (rtc_utc)
+        tm = gmtime(&ti);
+    else
+        tm = localtime(&ti);
+    rtc_set_date(s, tm);
+
+    val = to_bcd(s, (tm->tm_year / 100) + 19);
+    rtc_set_memory(s, REG_IBM_CENTURY_BYTE, val);
+    rtc_set_memory(s, REG_IBM_PS2_CENTURY_BYTE, val);
+}
+
 static void rtc_save(QEMUFile *f, void *opaque)
 {
     RTCState *s = opaque;
@@ -467,6 +491,8 @@ RTCState *rtc_init(int base, int irq)
     s->cmos_data[RTC_REG_C] = 0x00;
     s->cmos_data[RTC_REG_D] = 0x80;
 
+    rtc_set_date_from_host(s);
+
     s->periodic_timer = qemu_new_timer(vm_clock, 
                                        rtc_periodic_timer, s);
     s->second_timer = qemu_new_timer(vm_clock, 
diff --git a/tools/ioemu/hw/mips_int.c b/tools/ioemu/hw/mips_int.c
new file mode 100644 (file)
index 0000000..93d599f
--- /dev/null
@@ -0,0 +1,39 @@
+#include "vl.h"
+#include "cpu.h"
+
+/* Raise IRQ to CPU if necessary. It must be called every time the active
+   IRQ may change */
+void cpu_mips_update_irq(CPUState *env)
+{
+    if ((env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
+        (env->CP0_Status & (1 << CP0St_IE)) &&
+        !(env->hflags & MIPS_HFLAG_EXL) &&
+       !(env->hflags & MIPS_HFLAG_ERL) &&
+       !(env->hflags & MIPS_HFLAG_DM)) {
+        if (! (env->interrupt_request & CPU_INTERRUPT_HARD)) {
+            cpu_interrupt(env, CPU_INTERRUPT_HARD);
+       }
+    } else {
+        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+    }
+}
+
+void cpu_mips_irq_request(void *opaque, int irq, int level)
+{
+    CPUState *env = first_cpu;
+   
+    uint32_t mask;
+
+    if (irq >= 16)
+        return;
+
+    mask = 1 << (irq + CP0Ca_IP);
+
+    if (level) {
+        env->CP0_Cause |= mask;
+    } else {
+        env->CP0_Cause &= ~mask;
+    }
+    cpu_mips_update_irq(env);
+}
+
diff --git a/tools/ioemu/hw/mips_malta.c b/tools/ioemu/hw/mips_malta.c
new file mode 100644 (file)
index 0000000..029e18e
--- /dev/null
@@ -0,0 +1,590 @@
+/*
+ * QEMU Malta board support
+ *
+ * Copyright (c) 2006 Aurelien Jarno
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "vl.h"
+
+#ifdef TARGET_WORDS_BIGENDIAN
+#define BIOS_FILENAME "mips_bios.bin"
+#else
+#define BIOS_FILENAME "mipsel_bios.bin"
+#endif
+
+#ifdef MIPS_HAS_MIPS64
+#define INITRD_LOAD_ADDR       (int64_t)0x80800000
+#else
+#define INITRD_LOAD_ADDR       (int32_t)0x80800000
+#endif
+
+#define ENVP_ADDR              (int32_t)0x80002000
+#define VIRT_TO_PHYS_ADDEND    (-((int64_t)(int32_t)0x80000000))
+
+#define ENVP_NB_ENTRIES                16
+#define ENVP_ENTRY_SIZE                256
+
+
+extern FILE *logfile;
+
+typedef struct {
+    uint32_t leds;
+    uint32_t brk;
+    uint32_t gpout;
+    uint32_t i2coe;
+    uint32_t i2cout;
+    uint32_t i2csel;
+    CharDriverState *display;
+    char display_text[9];
+} MaltaFPGAState;
+
+static PITState *pit;
+
+/* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
+static void pic_irq_request(void *opaque, int level)
+{
+    cpu_mips_irq_request(opaque, 2, level);
+}
+
+/* Malta FPGA */
+static void malta_fpga_update_display(void *opaque)
+{
+    char leds_text[9];
+    int i;
+    MaltaFPGAState *s = opaque;
+
+    for (i = 7 ; i >= 0 ; i--) {
+        if (s->leds & (1 << i))
+            leds_text[i] = '#';
+       else
+            leds_text[i] = ' ';
+    }
+    leds_text[8] = '\0';
+
+    qemu_chr_printf(s->display, "\e[H\n\n|\e[32m%-8.8s\e[00m|\r\n", leds_text);
+    qemu_chr_printf(s->display, "\n\n\n\n|\e[31m%-8.8s\e[00m|", s->display_text);
+}
+
+static uint32_t malta_fpga_readl(void *opaque, target_phys_addr_t addr)
+{
+    MaltaFPGAState *s = opaque;
+    uint32_t val = 0;
+    uint32_t saddr;
+
+    saddr = (addr & 0xfffff);
+
+    switch (saddr) {
+
+    /* SWITCH Register */
+    case 0x00200:
+        val = 0x00000000;              /* All switches closed */
+       break;
+
+    /* STATUS Register */
+    case 0x00208:
+#ifdef TARGET_WORDS_BIGENDIAN
+        val = 0x00000012;
+#else
+        val = 0x00000010;
+#endif
+        break;
+
+    /* JMPRS Register */
+    case 0x00210:
+        val = 0x00;
+        break;
+
+    /* LEDBAR Register */
+    case 0x00408:
+        val = s->leds;
+        break;
+
+    /* BRKRES Register */
+    case 0x00508:
+        val = s->brk;
+        break;
+
+    /* GPOUT Register */
+    case 0x00a00:
+        val = s->gpout;
+        break;
+
+    /* XXX: implement a real I2C controller */
+
+    /* GPINP Register */
+    case 0x00a08:
+        /* IN = OUT until a real I2C control is implemented */
+        if (s->i2csel)
+            val = s->i2cout;
+        else
+            val = 0x00;
+        break;
+
+    /* I2CINP Register */
+    case 0x00b00:
+        val = 0x00000003;
+        break;
+
+    /* I2COE Register */
+    case 0x00b08:
+        val = s->i2coe;
+        break;
+
+    /* I2COUT Register */
+    case 0x00b10:
+        val = s->i2cout;
+        break;
+
+    /* I2CSEL Register */
+    case 0x00b18:
+        val = s->i2cout;
+        break;
+
+    default:
+#if 0
+        printf ("malta_fpga_read: Bad register offset 0x" TLSZ "\n",
+               addr);
+#endif
+        break;
+    }
+    return val;
+}
+
+static void malta_fpga_writel(void *opaque, target_phys_addr_t addr,
+                              uint32_t val)
+{
+    MaltaFPGAState *s = opaque;
+    uint32_t saddr;
+
+    saddr = (addr & 0xfffff);
+
+    switch (saddr) {
+
+    /* SWITCH Register */
+    case 0x00200:
+        break;
+
+    /* JMPRS Register */
+    case 0x00210:
+        break;
+
+    /* LEDBAR Register */
+    /* XXX: implement a 8-LED array */
+    case 0x00408:
+        s->leds = val & 0xff;
+        break;
+
+    /* ASCIIWORD Register */
+    case 0x00410:
+        snprintf(s->display_text, 9, "%08X", val);
+        malta_fpga_update_display(s);
+        break;
+
+    /* ASCIIPOS0 to ASCIIPOS7 Registers */
+    case 0x00418:
+    case 0x00420:
+    case 0x00428:
+    case 0x00430:
+    case 0x00438:
+    case 0x00440:
+    case 0x00448:
+    case 0x00450:
+        s->display_text[(saddr - 0x00418) >> 3] = (char) val;
+        malta_fpga_update_display(s);
+        break;
+
+    /* SOFTRES Register */
+    case 0x00500:
+        if (val == 0x42)
+            qemu_system_reset_request ();
+        break;
+
+    /* BRKRES Register */
+    case 0x00508:
+        s->brk = val & 0xff;
+        break;
+
+    /* GPOUT Register */
+    case 0x00a00:
+        s->gpout = val & 0xff;
+        break;
+
+    /* I2COE Register */
+    case 0x00b08:
+        s->i2coe = val & 0x03;
+        break;
+
+    /* I2COUT Register */
+    case 0x00b10:
+        s->i2cout = val & 0x03;
+        break;
+
+    /* I2CSEL Register */
+    case 0x00b18:
+        s->i2cout = val & 0x01;
+        break;
+
+    default:
+#if 0
+        printf ("malta_fpga_write: Bad register offset 0x" TLSZ "\n",
+               addr);
+#endif
+        break;
+    }
+}
+
+static CPUReadMemoryFunc *malta_fpga_read[] = {
+   malta_fpga_readl,
+   malta_fpga_readl,
+   malta_fpga_readl
+};
+
+static CPUWriteMemoryFunc *malta_fpga_write[] = {
+   malta_fpga_writel,
+   malta_fpga_writel,
+   malta_fpga_writel
+};
+
+void malta_fpga_reset(void *opaque)
+{
+    MaltaFPGAState *s = opaque;
+
+    s->leds   = 0x00;
+    s->brk    = 0x0a;
+    s->gpout  = 0x00;
+    s->i2coe  = 0x0;
+    s->i2cout = 0x3;
+    s->i2csel = 0x1;
+
+    s->display_text[8] = '\0';
+    snprintf(s->display_text, 9, "        ");
+    malta_fpga_update_display(s);
+}
+
+MaltaFPGAState *malta_fpga_init(target_phys_addr_t base)
+{
+    MaltaFPGAState *s;
+    int malta;
+
+    s = (MaltaFPGAState *)qemu_mallocz(sizeof(MaltaFPGAState));
+
+    malta = cpu_register_io_memory(0, malta_fpga_read,
+                                   malta_fpga_write, s);
+    cpu_register_physical_memory(base, 0x100000, malta);
+
+    s->display = qemu_chr_open("vc");
+    qemu_chr_printf(s->display, "\e[HMalta LEDBAR\r\n");
+    qemu_chr_printf(s->display, "+--------+\r\n");
+    qemu_chr_printf(s->display, "+        +\r\n");
+    qemu_chr_printf(s->display, "+--------+\r\n");
+    qemu_chr_printf(s->display, "\n");
+    qemu_chr_printf(s->display, "Malta ASCII\r\n");
+    qemu_chr_printf(s->display, "+--------+\r\n");
+    qemu_chr_printf(s->display, "+        +\r\n");
+    qemu_chr_printf(s->display, "+--------+\r\n");
+
+    malta_fpga_reset(s);
+    qemu_register_reset(malta_fpga_reset, s);
+
+    return s;
+}
+
+/* Audio support */
+#ifdef HAS_AUDIO
+static void audio_init (PCIBus *pci_bus)
+{
+    struct soundhw *c;
+    int audio_enabled = 0;
+
+    for (c = soundhw; !audio_enabled && c->name; ++c) {
+        audio_enabled = c->enabled;
+    }
+
+    if (audio_enabled) {
+        AudioState *s;
+
+        s = AUD_init ();
+        if (s) {
+            for (c = soundhw; c->name; ++c) {
+                if (c->enabled) {
+                    if (c->isa) {
+                        fprintf(stderr, "qemu: Unsupported Sound Card: %s\n", c->name);
+                        exit(1);
+                    }
+                    else {
+                        if (pci_bus) {
+                            c->init.init_pci (pci_bus, s);
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+#endif
+
+/* Network support */
+static void network_init (PCIBus *pci_bus)
+{
+    int i;
+    NICInfo *nd;
+
+    for(i = 0; i < nb_nics; i++) {
+        nd = &nd_table[i];
+        if (!nd->model) {
+            nd->model = "pcnet";
+        }
+        if (i == 0  && strcmp(nd->model, "pcnet") == 0) {
+            /* The malta board has a PCNet card using PCI SLOT 11 */
+            pci_nic_init(pci_bus, nd, 88);
+        } else {
+            pci_nic_init(pci_bus, nd, -1);
+        }
+    }
+}
+
+/* ROM and pseudo bootloader
+
+   The following code implements a very very simple bootloader. It first
+   loads the registers a0 to a3 to the values expected by the OS, and
+   then jump at the kernel address.
+
+   The bootloader should pass the locations of the kernel arguments and
+   environment variables tables. Those tables contain the 32-bit address
+   of NULL terminated strings. The environment variables table should be
+   terminated by a NULL address.
+
+   For a simpler implementation, the number of kernel arguments is fixed
+   to two (the name of the kernel and the command line), and the two
+   tables are actually the same one.
+
+   The registers a0 to a3 should contain the following values:
+     a0 - number of kernel arguments
+     a1 - 32-bit address of the kernel arguments table
+     a2 - 32-bit address of the environment variables table
+     a3 - RAM size in bytes
+*/
+
+static void write_bootloader (CPUState *env, unsigned long bios_offset, int64_t kernel_addr)
+{
+    uint32_t *p;
+
+    /* Small bootloader */
+    p = (uint32_t *) (phys_ram_base + bios_offset);
+    stl_raw(p++, 0x0bf00010);                                      /* j 0x1fc00040 */
+    stl_raw(p++, 0x00000000);                                      /* nop */
+
+    /* Second part of the bootloader */
+    p = (uint32_t *) (phys_ram_base + bios_offset + 0x040);
+    stl_raw(p++, 0x3c040000);                                      /* lui a0, 0 */
+    stl_raw(p++, 0x34840002);                                      /* ori a0, a0, 2 */
+    stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff));       /* lui a1, high(ENVP_ADDR) */
+    stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff));               /* ori a1, a0, low(ENVP_ADDR) */
+    stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
+    stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff));         /* ori a2, a2, low(ENVP_ADDR + 8) */
+    stl_raw(p++, 0x3c070000 | (env->ram_size >> 16));              /* lui a3, high(env->ram_size) */
+    stl_raw(p++, 0x34e70000 | (env->ram_size & 0xffff));           /* ori a3, a3, low(env->ram_size) */
+    stl_raw(p++, 0x3c1f0000 | ((kernel_addr >> 16) & 0xffff));     /* lui ra, high(kernel_addr) */;
+    stl_raw(p++, 0x37ff0000 | (kernel_addr & 0xffff));             /* ori ra, ra, low(kernel_addr) */
+    stl_raw(p++, 0x03e00008);                                      /* jr ra */
+    stl_raw(p++, 0x00000000);                                      /* nop */
+}
+
+static void prom_set(int index, const char *string, ...)
+{
+    va_list ap;
+    int32_t *p;
+    int32_t table_addr;
+    char *s;
+
+    if (index >= ENVP_NB_ENTRIES)
+        return;
+
+    p = (int32_t *) (phys_ram_base + ENVP_ADDR + VIRT_TO_PHYS_ADDEND);
+    p += index;
+
+    if (string == NULL) {
+        stl_raw(p, 0);
+        return;
+    }
+
+    table_addr = ENVP_ADDR + sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;
+    s = (char *) (phys_ram_base + VIRT_TO_PHYS_ADDEND + table_addr);
+
+    stl_raw(p, table_addr);
+
+    va_start(ap, string);
+    vsnprintf (s, ENVP_ENTRY_SIZE, string, ap);
+    va_end(ap);
+}
+
+/* Kernel */
+static int64_t load_kernel (CPUState *env)
+{
+    int64_t kernel_addr = 0;
+    int index = 0;
+    long initrd_size;
+
+    if (load_elf(env->kernel_filename, VIRT_TO_PHYS_ADDEND, &kernel_addr) < 0) {
+        fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                env->kernel_filename);
+      exit(1);
+    }
+
+    /* load initrd */
+    initrd_size = 0;
+    if (env->initrd_filename) {
+        initrd_size = load_image(env->initrd_filename,
+                                 phys_ram_base + INITRD_LOAD_ADDR + VIRT_TO_PHYS_ADDEND);
+        if (initrd_size == (target_ulong) -1) {
+            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
+                    env->initrd_filename);
+            exit(1);
+        }
+    }
+
+    /* Store command line.  */
+    prom_set(index++, env->kernel_filename);
+    if (initrd_size > 0)
+        prom_set(index++, "rd_start=0x" TLSZ " rd_size=%li %s", INITRD_LOAD_ADDR, initrd_size, env->kernel_cmdline);
+    else
+        prom_set(index++, env->kernel_cmdline);
+
+    /* Setup minimum environment variables */
+    prom_set(index++, "memsize");
+    prom_set(index++, "%i", env->ram_size);
+    prom_set(index++, "modetty0");
+    prom_set(index++, "38400n8r");
+    prom_set(index++, NULL);
+
+    return kernel_addr;
+}
+
+static void main_cpu_reset(void *opaque)
+{
+    CPUState *env = opaque;
+    cpu_reset(env);
+
+    /* The bootload does not need to be rewritten as it is located in a
+       read only location. The kernel location and the arguments table
+       location does not change. */
+    if (env->kernel_filename)
+        load_kernel (env);
+}
+
+void mips_malta_init (int ram_size, int vga_ram_size, int boot_device,
+                      DisplayState *ds, const char **fd_filename, int snapshot,
+                      const char *kernel_filename, const char *kernel_cmdline,
+                      const char *initrd_filename)
+{
+    char buf[1024];
+    unsigned long bios_offset;
+    int64_t kernel_addr;
+    PCIBus *pci_bus;
+    CPUState *env;
+    RTCState *rtc_state;
+    /* fdctrl_t *floppy_controller; */
+    MaltaFPGAState *malta_fpga;
+    int ret;
+
+    env = cpu_init();
+    register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
+    qemu_register_reset(main_cpu_reset, env);
+
+    /* allocate RAM */
+    cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
+
+    /* Map the bios at two physical locations, as on the real board */
+    bios_offset = ram_size + vga_ram_size;
+    cpu_register_physical_memory(0x1e000000LL,
+                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);
+    cpu_register_physical_memory(0x1fc00000LL,
+                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);
+
+    /* Load a BIOS image except if a kernel image has been specified. In
+       the later case, just write a small bootloader to the flash
+       location. */
+    if (kernel_filename) {
+        env->ram_size = ram_size;
+        env->kernel_filename = kernel_filename;
+        env->kernel_cmdline = kernel_cmdline;
+        env->initrd_filename = initrd_filename;
+        kernel_addr = load_kernel(env);
+        write_bootloader(env, bios_offset, kernel_addr);
+    } else {
+        snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
+        ret = load_image(buf, phys_ram_base + bios_offset);
+        if (ret != BIOS_SIZE) {
+            fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s'\n",
+                    buf);
+            exit(1);
+        }
+    }
+
+    /* Board ID = 0x420 (Malta Board with CoreLV)
+       XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
+       map to the board ID. */
+    stl_raw(phys_ram_base + bios_offset + 0x10, 0x00000420);
+
+    /* Init internal devices */
+    cpu_mips_clock_init(env);
+    cpu_mips_irqctrl_init();
+
+    /* FPGA */
+    malta_fpga = malta_fpga_init(0x1f000000LL);
+
+    /* Interrupt controller */
+    isa_pic = pic_init(pic_irq_request, env);
+
+    /* Northbridge */
+    pci_bus = pci_gt64120_init(isa_pic);
+
+    /* Southbridge */
+    piix4_init(pci_bus, 80);
+    pci_piix3_ide_init(pci_bus, bs_table, 81);
+    usb_uhci_init(pci_bus, 82);
+    piix4_pm_init(pci_bus, 83);
+    pit = pit_init(0x40, 0);
+    DMA_init(0);
+
+    /* Super I/O */
+    kbd_init();
+    rtc_state = rtc_init(0x70, 8);
+    serial_init(&pic_set_irq_new, isa_pic, 0x3f8, 4, serial_hds[0]);
+    parallel_init(0x378, 7, parallel_hds[0]);
+    /* XXX: The floppy controller does not work correctly, something is
+       probably wrong.
+    floppy_controller = fdctrl_init(6, 2, 0, 0x3f0, fd_table); */
+
+    /* Sound card */
+#ifdef HAS_AUDIO
+    audio_init(pci_bus);
+#endif
+
+    /* Network card */
+    network_init(pci_bus);
+}
+
+QEMUMachine mips_malta_machine = {
+    "malta",
+    "MIPS Malta Core LV",
+    mips_malta_init,
+};
index 22d742a2e3628e5011e15940d8cde404bfbd3a44..8d1cac93929ee7a0b087e4082634fb12920f656a 100644 (file)
+/*
+ * QEMU/MIPS pseudo-board
+ *
+ * emulates a simple machine with ISA-like bus.
+ * ISA IO space mapped to the 0x14000000 (PHYS) and
+ * ISA memory at the 0x10000000 (PHYS, 16Mb in size).
+ * All peripherial devices are attached to this "bus" with
+ * the standard PC ISA addresses.
+*/
 #include "vl.h"
 
+#ifdef TARGET_WORDS_BIGENDIAN
 #define BIOS_FILENAME "mips_bios.bin"
-//#define BIOS_FILENAME "system.bin"
-#define KERNEL_LOAD_ADDR 0x80010000
-#define INITRD_LOAD_ADDR 0x80800000
+#else
+#define BIOS_FILENAME "mipsel_bios.bin"
+#endif
 
-#define VIRT_TO_PHYS_ADDEND (-0x80000000LL)
+#ifdef MIPS_HAS_MIPS64
+#define INITRD_LOAD_ADDR (int64_t)(int32_t)0x80800000
+#else
+#define INITRD_LOAD_ADDR (int32_t)0x80800000
+#endif
 
-extern FILE *logfile;
+#define VIRT_TO_PHYS_ADDEND (-((int64_t)(int32_t)0x80000000))
 
-static PITState *pit;
+static const int ide_iobase[2] = { 0x1f0, 0x170 };
+static const int ide_iobase2[2] = { 0x3f6, 0x376 };
+static const int ide_irq[2] = { 14, 15 };
 
-static void pic_irq_request(void *opaque, int level)
-{
-    CPUState *env = first_cpu;
-    if (level) {
-        env->CP0_Cause |= 0x00000400;
-        cpu_interrupt(env, CPU_INTERRUPT_HARD);
-    } else {
-       env->CP0_Cause &= ~0x00000400;
-        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
-    }
-}
+static int serial_io[MAX_SERIAL_PORTS] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
+static int serial_irq[MAX_SERIAL_PORTS] = { 4, 3, 4, 3 };
 
-void cpu_mips_irqctrl_init (void)
-{
-}
+extern FILE *logfile;
 
-/* XXX: do not use a global */
-uint32_t cpu_mips_get_random (CPUState *env)
-{
-    static uint32_t seed = 0;
-    uint32_t idx;
-    seed = seed * 314159 + 1;
-    idx = (seed >> 16) % (MIPS_TLB_NB - env->CP0_Wired) + env->CP0_Wired;
-    return idx;
-}
+static PITState *pit; /* PIT i8254 */
 
-/* MIPS R4K timer */
-uint32_t cpu_mips_get_count (CPUState *env)
-{
-    return env->CP0_Count +
-        (uint32_t)muldiv64(qemu_get_clock(vm_clock),
-                           100 * 1000 * 1000, ticks_per_sec);
-}
-
-static void cpu_mips_update_count (CPUState *env, uint32_t count,
-                                   uint32_t compare)
+/*i8254 PIT is attached to the IRQ0 at PIC i8259 */
+/*The PIC is attached to the MIPS CPU INT0 pin */
+static void pic_irq_request(void *opaque, int level)
 {
-    uint64_t now, next;
-    uint32_t tmp;
-    
-    tmp = count;
-    if (count == compare)
-        tmp++;
-    now = qemu_get_clock(vm_clock);
-    next = now + muldiv64(compare - tmp, ticks_per_sec, 100 * 1000 * 1000);
-    if (next == now)
-       next++;
-#if 0
-    if (logfile) {
-        fprintf(logfile, "%s: 0x%08" PRIx64 " %08x %08x => 0x%08" PRIx64 "\n",
-                __func__, now, count, compare, next - now);
-    }
-#endif
-    /* Store new count and compare registers */
-    env->CP0_Compare = compare;
-    env->CP0_Count =
-        count - (uint32_t)muldiv64(now, 100 * 1000 * 1000, ticks_per_sec);
-    /* Adjust timer */
-    qemu_mod_timer(env->timer, next);
+    cpu_mips_irq_request(opaque, 2, level);
 }
 
-void cpu_mips_store_count (CPUState *env, uint32_t value)
+static void mips_qemu_writel (void *opaque, target_phys_addr_t addr,
+                             uint32_t val)
 {
-    cpu_mips_update_count(env, value, env->CP0_Compare);
+    if ((addr & 0xffff) == 0 && val == 42)
+        qemu_system_reset_request ();
+    else if ((addr & 0xffff) == 4 && val == 42)
+        qemu_system_shutdown_request ();
 }
 
-void cpu_mips_store_compare (CPUState *env, uint32_t value)
+static uint32_t mips_qemu_readl (void *opaque, target_phys_addr_t addr)
 {
-    cpu_mips_update_count(env, cpu_mips_get_count(env), value);
-    env->CP0_Cause &= ~0x00008000;
-    cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+    return 0;
 }
 
-static void mips_timer_cb (void *opaque)
-{
-    CPUState *env;
-
-    env = opaque;
-#if 0
-    if (logfile) {
-        fprintf(logfile, "%s\n", __func__);
-    }
-#endif
-    cpu_mips_update_count(env, cpu_mips_get_count(env), env->CP0_Compare);
-    env->CP0_Cause |= 0x00008000;
-    cpu_interrupt(env, CPU_INTERRUPT_HARD);
-}
+static CPUWriteMemoryFunc *mips_qemu_write[] = {
+    &mips_qemu_writel,
+    &mips_qemu_writel,
+    &mips_qemu_writel,
+};
 
-void cpu_mips_clock_init (CPUState *env)
-{
-    env->timer = qemu_new_timer(vm_clock, &mips_timer_cb, env);
-    env->CP0_Compare = 0;
-    cpu_mips_update_count(env, 1, 0);
-}
+static CPUReadMemoryFunc *mips_qemu_read[] = {
+    &mips_qemu_readl,
+    &mips_qemu_readl,
+    &mips_qemu_readl,
+};
 
+static int mips_qemu_iomemtype = 0;
 
-static void io_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
+void load_kernel (CPUState *env, int ram_size, const char *kernel_filename,
+                 const char *kernel_cmdline,
+                 const char *initrd_filename)
 {
-#if 0
-    if (logfile)
-        fprintf(logfile, "%s: addr %08x val %08x\n", __func__, addr, value);
-#endif
-    cpu_outb(NULL, addr & 0xffff, value);
-}
+    int64_t entry = 0;
+    long kernel_size, initrd_size;
 
-static uint32_t io_readb (void *opaque, target_phys_addr_t addr)
-{
-    uint32_t ret = cpu_inb(NULL, addr & 0xffff);
-#if 0
-    if (logfile)
-        fprintf(logfile, "%s: addr %08x val %08x\n", __func__, addr, ret);
-#endif
-    return ret;
-}
+    kernel_size = load_elf(kernel_filename, VIRT_TO_PHYS_ADDEND, &entry);
+    if (kernel_size >= 0) {
+        if ((entry & ~0x7fffffffULL) == 0x80000000)
+            entry = (int32_t)entry;
+        env->PC = entry;
+    } else {
+        fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                kernel_filename);
+        exit(1);
+    }
 
-static void io_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
-{
-#if 0
-    if (logfile)
-        fprintf(logfile, "%s: addr %08x val %08x\n", __func__, addr, value);
-#endif
-#ifdef TARGET_WORDS_BIGENDIAN
-    value = bswap16(value);
-#endif
-    cpu_outw(NULL, addr & 0xffff, value);
-}
+    /* load initrd */
+    initrd_size = 0;
+    if (initrd_filename) {
+        initrd_size = load_image(initrd_filename,
+                                 phys_ram_base + INITRD_LOAD_ADDR + VIRT_TO_PHYS_ADDEND);
+        if (initrd_size == (target_ulong) -1) {
+            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
+                    initrd_filename);
+            exit(1);
+        }
+    }
 
-static uint32_t io_readw (void *opaque, target_phys_addr_t addr)
-{
-    uint32_t ret = cpu_inw(NULL, addr & 0xffff);
-#ifdef TARGET_WORDS_BIGENDIAN
-    ret = bswap16(ret);
-#endif
-#if 0
-    if (logfile)
-        fprintf(logfile, "%s: addr %08x val %08x\n", __func__, addr, ret);
-#endif
-    return ret;
-}
+    /* Store command line.  */
+    if (initrd_size > 0) {
+        int ret;
+        ret = sprintf(phys_ram_base + (16 << 20) - 256,
+                      "rd_start=0x" TLSZ " rd_size=%li ",
+                      INITRD_LOAD_ADDR,
+                      initrd_size);
+        strcpy (phys_ram_base + (16 << 20) - 256 + ret, kernel_cmdline);
+    }
+    else {
+        strcpy (phys_ram_base + (16 << 20) - 256, kernel_cmdline);
+    }
 
-static void io_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
-{
-#if 0
-    if (logfile)
-        fprintf(logfile, "%s: addr %08x val %08x\n", __func__, addr, value);
-#endif
-#ifdef TARGET_WORDS_BIGENDIAN
-    value = bswap32(value);
-#endif
-    cpu_outl(NULL, addr & 0xffff, value);
+    *(int32_t *)(phys_ram_base + (16 << 20) - 260) = tswap32 (0x12345678);
+    *(int32_t *)(phys_ram_base + (16 << 20) - 264) = tswap32 (ram_size);
 }
 
-static uint32_t io_readl (void *opaque, target_phys_addr_t addr)
+static void main_cpu_reset(void *opaque)
 {
-    uint32_t ret = cpu_inl(NULL, addr & 0xffff);
+    CPUState *env = opaque;
+    cpu_reset(env);
 
-#ifdef TARGET_WORDS_BIGENDIAN
-    ret = bswap32(ret);
-#endif
-#if 0
-    if (logfile)
-        fprintf(logfile, "%s: addr %08x val %08x\n", __func__, addr, ret);
-#endif
-    return ret;
+    if (env->kernel_filename)
+        load_kernel (env, env->ram_size, env->kernel_filename,
+                     env->kernel_cmdline, env->initrd_filename);
 }
 
-CPUWriteMemoryFunc *io_write[] = {
-    &io_writeb,
-    &io_writew,
-    &io_writel,
-};
-
-CPUReadMemoryFunc *io_read[] = {
-    &io_readb,
-    &io_readw,
-    &io_readl,
-};
-
 void mips_r4k_init (int ram_size, int vga_ram_size, int boot_device,
                     DisplayState *ds, const char **fd_filename, int snapshot,
                     const char *kernel_filename, const char *kernel_cmdline,
                     const char *initrd_filename)
 {
     char buf[1024];
-    int64_t entry = 0;
     unsigned long bios_offset;
-    int io_memory;
-    int ret;
+    int bios_size;
     CPUState *env;
-    long kernel_size;
+    static RTCState *rtc_state;
+    int i;
 
     env = cpu_init();
     register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
+    qemu_register_reset(main_cpu_reset, env);
 
     /* allocate RAM */
     cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
 
+    if (!mips_qemu_iomemtype) {
+        mips_qemu_iomemtype = cpu_register_io_memory(0, mips_qemu_read,
+                                                    mips_qemu_write, NULL);
+    }
+    cpu_register_physical_memory(0x1fbf0000, 0x10000, mips_qemu_iomemtype);
+
     /* Try to load a BIOS image. If this fails, we continue regardless,
        but initialize the hardware ourselves. When a kernel gets
        preloaded we also initialize the hardware, since the BIOS wasn't
        run. */
     bios_offset = ram_size + vga_ram_size;
     snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
-    ret = load_image(buf, phys_ram_base + bios_offset);
-    if (ret == BIOS_SIZE) {
-       cpu_register_physical_memory((uint32_t)(0x1fc00000),
+    bios_size = load_image(buf, phys_ram_base + bios_offset);
+    if ((bios_size > 0) && (bios_size <= BIOS_SIZE)) {
+       cpu_register_physical_memory(0x1fc00000,
                                     BIOS_SIZE, bios_offset | IO_MEM_ROM);
     } else {
        /* not fatal */
@@ -224,54 +167,37 @@ void mips_r4k_init (int ram_size, int vga_ram_size, int boot_device,
                buf);
     }
 
-    kernel_size = 0;
     if (kernel_filename) {
-       kernel_size = load_elf(kernel_filename, VIRT_TO_PHYS_ADDEND, &entry);
-       if (kernel_size >= 0)
-           env->PC = entry;
-       else {
-           kernel_size = load_image(kernel_filename,
-                                     phys_ram_base + KERNEL_LOAD_ADDR + VIRT_TO_PHYS_ADDEND);
-            if (kernel_size < 0) {
-                fprintf(stderr, "qemu: could not load kernel '%s'\n",
-                        kernel_filename);
-                exit(1);
-            }
-            env->PC = KERNEL_LOAD_ADDR;
-       }
-
-        /* load initrd */
-        if (initrd_filename) {
-            if (load_image(initrd_filename,
-                          phys_ram_base + INITRD_LOAD_ADDR + VIRT_TO_PHYS_ADDEND)
-               == (target_ulong) -1) {
-                fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", 
-                        initrd_filename);
-                exit(1);
-            }
-        }
-
-       /* Store command line.  */
-        strcpy (phys_ram_base + (16 << 20) - 256, kernel_cmdline);
-        /* FIXME: little endian support */
-        *(int *)(phys_ram_base + (16 << 20) - 260) = tswap32 (0x12345678);
-        *(int *)(phys_ram_base + (16 << 20) - 264) = tswap32 (ram_size);
+        load_kernel (env, ram_size, kernel_filename, kernel_cmdline,
+                    initrd_filename);
+       env->ram_size = ram_size;
+       env->kernel_filename = kernel_filename;
+       env->kernel_cmdline = kernel_cmdline;
+       env->initrd_filename = initrd_filename;
     }
 
-    /* Init internal devices */
+    /* Init CPU internal devices */
     cpu_mips_clock_init(env);
     cpu_mips_irqctrl_init();
 
+    rtc_state = rtc_init(0x70, 8);
+
     /* Register 64 KB of ISA IO space at 0x14000000 */
-    io_memory = cpu_register_io_memory(0, io_read, io_write, NULL);
-    cpu_register_physical_memory(0x14000000, 0x00010000, io_memory);
+    isa_mmio_init(0x14000000, 0x00010000);
     isa_mem_base = 0x10000000;
 
     isa_pic = pic_init(pic_irq_request, env);
     pit = pit_init(0x40, 0);
-    serial_init(&pic_set_irq_new, isa_pic, 0x3f8, 4, serial_hds[0]);
-    vga_initialize(NULL, ds, phys_ram_base + ram_size, ram_size, 
-                   vga_ram_size, 0, 0);
+
+    for(i = 0; i < MAX_SERIAL_PORTS; i++) {
+        if (serial_hds[i]) {
+            serial_init(&pic_set_irq_new, isa_pic,
+                        serial_io[i], serial_irq[i], serial_hds[i]);
+        }
+    }
+
+    isa_vga_init(ds, phys_ram_base + ram_size, ram_size, 
+                 vga_ram_size);
 
     if (nd_table[0].vlan) {
         if (nd_table[0].model == NULL
@@ -282,6 +208,10 @@ void mips_r4k_init (int ram_size, int vga_ram_size, int boot_device,
             exit (1);
         }
     }
+
+    for(i = 0; i < 2; i++)
+        isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
+                     bs_table[2 * i], bs_table[2 * i + 1]);
 }
 
 QEMUMachine mips_machine = {
diff --git a/tools/ioemu/hw/mips_timer.c b/tools/ioemu/hw/mips_timer.c
new file mode 100644 (file)
index 0000000..bc83036
--- /dev/null
@@ -0,0 +1,83 @@
+#include "vl.h"
+
+void cpu_mips_irqctrl_init (void)
+{
+}
+
+/* XXX: do not use a global */
+uint32_t cpu_mips_get_random (CPUState *env)
+{
+    static uint32_t seed = 0;
+    uint32_t idx;
+    seed = seed * 314159 + 1;
+    idx = (seed >> 16) % (MIPS_TLB_NB - env->CP0_Wired) + env->CP0_Wired;
+    return idx;
+}
+
+/* MIPS R4K timer */
+uint32_t cpu_mips_get_count (CPUState *env)
+{
+    return env->CP0_Count +
+        (uint32_t)muldiv64(qemu_get_clock(vm_clock),
+                           100 * 1000 * 1000, ticks_per_sec);
+}
+
+static void cpu_mips_update_count (CPUState *env, uint32_t count,
+                                   uint32_t compare)
+{
+    uint64_t now, next;
+    uint32_t tmp;
+
+    tmp = count;
+    if (count == compare)
+        tmp++;
+    now = qemu_get_clock(vm_clock);
+    next = now + muldiv64(compare - tmp, ticks_per_sec, 100 * 1000 * 1000);
+    if (next == now)
+       next++;
+#if 0
+    if (logfile) {
+        fprintf(logfile, "%s: 0x%08" PRIx64 " %08x %08x => 0x%08" PRIx64 "\n",
+                __func__, now, count, compare, next - now);
+    }
+#endif
+    /* Store new count and compare registers */
+    env->CP0_Compare = compare;
+    env->CP0_Count =
+        count - (uint32_t)muldiv64(now, 100 * 1000 * 1000, ticks_per_sec);
+    /* Adjust timer */
+    qemu_mod_timer(env->timer, next);
+}
+
+void cpu_mips_store_count (CPUState *env, uint32_t value)
+{
+    cpu_mips_update_count(env, value, env->CP0_Compare);
+}
+
+void cpu_mips_store_compare (CPUState *env, uint32_t value)
+{
+    cpu_mips_update_count(env, cpu_mips_get_count(env), value);
+    cpu_mips_irq_request(env, 7, 0);
+}
+
+static void mips_timer_cb (void *opaque)
+{
+    CPUState *env;
+
+    env = opaque;
+#if 0
+    if (logfile) {
+        fprintf(logfile, "%s\n", __func__);
+    }
+#endif
+    cpu_mips_update_count(env, cpu_mips_get_count(env), env->CP0_Compare);
+    cpu_mips_irq_request(env, 7, 1);
+}
+
+void cpu_mips_clock_init (CPUState *env)
+{
+    env->timer = qemu_new_timer(vm_clock, &mips_timer_cb, env);
+    env->CP0_Compare = 0;
+    cpu_mips_update_count(env, 1, 0);
+}
+
index 78f341372bb4afd054b2405771bcb0afd80e0c4d..92720e0811c6d3d43cb4eb3a01577ad696438986 100644 (file)
@@ -340,7 +340,7 @@ static void ne2000_receive(void *opaque, const uint8_t *buf, int size)
     }
     s->curpag = next >> 8;
 
-    /* now we can signal we have receive something */
+    /* now we can signal we have received something */
     s->isr |= ENISR_RX;
     ne2000_update_irq(s);
 }
@@ -679,6 +679,9 @@ static void ne2000_save(QEMUFile* f,void* opaque)
 {
        NE2000State* s=(NE2000State*)opaque;
 
+        if (s->pci_dev)
+            pci_device_save(s->pci_dev, f);
+
         qemu_put_8s(f, &s->rxcr);
 
        qemu_put_8s(f, &s->cmd);
@@ -704,13 +707,21 @@ static void ne2000_save(QEMUFile* f,void* opaque)
 static int ne2000_load(QEMUFile* f,void* opaque,int version_id)
 {
        NE2000State* s=(NE2000State*)opaque;
+        int ret;
+
+        if (version_id > 3)
+            return -EINVAL;
+
+        if (s->pci_dev && version_id >= 3) {
+            ret = pci_device_load(s->pci_dev, f);
+            if (ret < 0)
+                return ret;
+        }
 
-        if (version_id == 2) {
+        if (version_id >= 2) {
             qemu_get_8s(f, &s->rxcr);
-        } else if (version_id == 1) {
-            s->rxcr = 0x0c;
         } else {
-            return -EINVAL;
+            s->rxcr = 0x0c;
         }
 
        qemu_get_8s(f, &s->cmd);
@@ -801,16 +812,15 @@ static void ne2000_map(PCIDevice *pci_dev, int region_num,
     register_ioport_read(addr + 0x1f, 1, 1, ne2000_reset_ioport_read, s);
 }
 
-void pci_ne2000_init(PCIBus *bus, NICInfo *nd)
+void pci_ne2000_init(PCIBus *bus, NICInfo *nd, int devfn)
 {
     PCINE2000State *d;
     NE2000State *s;
     uint8_t *pci_conf;
-    int instance;
     
     d = (PCINE2000State *)pci_register_device(bus,
                                               "NE2000", sizeof(PCINE2000State),
-                                              -1
+                                              devfn
                                               NULL, NULL);
     pci_conf = d->dev.config;
     pci_conf[0x00] = 0xec; // Realtek 8029
@@ -841,8 +851,6 @@ void pci_ne2000_init(PCIBus *bus, NICInfo *nd)
              s->macaddr[4],
              s->macaddr[5]);
              
-    instance = pci_bus_num(bus) << 8 | s->pci_dev->devfn;
-    register_savevm("ne2000", instance, 2, ne2000_save, ne2000_load, s);
-    register_savevm("ne2000_pci", instance, 1, generic_pci_save, 
-                    generic_pci_load, &d->dev);
+    /* XXX: instance number ? */
+    register_savevm("ne2000", 0, 3, ne2000_save, ne2000_load, s);
 }
index 952e4ee983ffad1501ff5dc360cf222fa400e549..a43e866bc71979f5aab5144c3fd8f2a553454bde 100644 (file)
@@ -44,6 +44,7 @@ static PITState *pit;
 #ifndef CONFIG_DM
 static IOAPICState *ioapic;
 #endif /* !CONFIG_DM */
+static PCIDevice *i440fx_state;
 
 static void ioport80_write(void *opaque, uint32_t addr, uint32_t data)
 {
@@ -78,6 +79,14 @@ uint64_t cpu_get_tsc(CPUX86State *env)
 }
 
 #ifndef CONFIG_DM
+/* SMM support */
+void cpu_smm_update(CPUState *env)
+{
+    if (i440fx_state && env == first_cpu)
+        i440fx_set_smm(i440fx_state, (env->hflags >> HF_SMM_SHIFT) & 1);
+}
+
+
 /* IRQ handling */
 int cpu_get_pic_interrupt(CPUState *env)
 {
@@ -108,14 +117,6 @@ static void pic_irq_request(void *opaque, int level)
 /* PC cmos mappings */
 
 #define REG_EQUIPMENT_BYTE          0x14
-#define REG_IBM_CENTURY_BYTE        0x32
-#define REG_IBM_PS2_CENTURY_BYTE    0x37
-
-
-static inline int to_bcd(RTCState *s, int a)
-{
-    return ((a / 10) << 4) | (a % 10);
-}
 
 static int cmos_get_fd_drive_type(int fd0)
 {
@@ -181,23 +182,8 @@ static void cmos_init(uint64_t ram_size, char *boot_device, BlockDriverState **h
     RTCState *s = rtc_state;
     int val;
     int fd0, fd1, nb;
-    time_t ti;
-    struct tm *tm;
     int i;
 
-    /* set the CMOS date */
-    time(&ti);
-    ti += timeoffset;
-    if (rtc_utc)
-        tm = gmtime(&ti);
-    else
-        tm = localtime(&ti);
-    rtc_set_date(s, tm);
-
-    val = to_bcd(s, (tm->tm_year / 100) + 19);
-    rtc_set_memory(s, REG_IBM_CENTURY_BYTE, val);
-    rtc_set_memory(s, REG_IBM_PS2_CENTURY_BYTE, val);
-
     /* various important CMOS locations needed by PC/Bochs bios */
 
     /* memory size */
@@ -415,158 +401,6 @@ static void main_cpu_reset(void *opaque)
     cpu_reset(env);
 }
 
-/*************************************************/
-
-#ifndef CONFIG_DM
-static void putb(uint8_t **pp, int val)
-{
-    uint8_t *q;
-    q = *pp;
-    *q++ = val;
-    *pp = q;
-}
-
-static void putstr(uint8_t **pp, const char *str)
-{
-    uint8_t *q;
-    q = *pp;
-    while (*str)
-        *q++ = *str++;
-    *pp = q;
-}
-
-static void putle16(uint8_t **pp, int val)
-{
-    uint8_t *q;
-    q = *pp;
-    *q++ = val;
-    *q++ = val >> 8;
-    *pp = q;
-}
-
-static void putle32(uint8_t **pp, int val)
-{
-    uint8_t *q;
-    q = *pp;
-    *q++ = val;
-    *q++ = val >> 8;
-    *q++ = val >> 16;
-    *q++ = val >> 24;
-    *pp = q;
-}
-
-static int mpf_checksum(const uint8_t *data, int len)
-{
-    int sum, i;
-    sum = 0;
-    for(i = 0; i < len; i++)
-        sum += data[i];
-    return sum & 0xff;
-}
-
-/* Build the Multi Processor table in the BIOS. Same values as Bochs. */
-static void bios_add_mptable(uint8_t *bios_data)
-{
-    uint8_t *mp_config_table, *q, *float_pointer_struct;
-    int ioapic_id, offset, i, len;
-    
-    if (smp_cpus <= 1)
-        return;
-
-    mp_config_table = bios_data + 0xb000;
-    q = mp_config_table;
-    putstr(&q, "PCMP"); /* "PCMP signature */
-    putle16(&q, 0); /* table length (patched later) */
-    putb(&q, 4); /* spec rev */
-    putb(&q, 0); /* checksum (patched later) */
-    putstr(&q, "QEMUCPU "); /* OEM id */
-    putstr(&q, "0.1         "); /* vendor id */
-    putle32(&q, 0); /* OEM table ptr */
-    putle16(&q, 0); /* OEM table size */
-    putle16(&q, 20); /* entry count */
-    putle32(&q, 0xfee00000); /* local APIC addr */
-    putle16(&q, 0); /* ext table length */
-    putb(&q, 0); /* ext table checksum */
-    putb(&q, 0); /* reserved */
-    
-    for(i = 0; i < smp_cpus; i++) {
-        putb(&q, 0); /* entry type = processor */
-        putb(&q, i); /* APIC id */
-        putb(&q, 0x11); /* local APIC version number */
-        if (i == 0)
-            putb(&q, 3); /* cpu flags: enabled, bootstrap cpu */
-        else
-            putb(&q, 1); /* cpu flags: enabled */
-        putb(&q, 0); /* cpu signature */
-        putb(&q, 6);
-        putb(&q, 0);
-        putb(&q, 0);
-        putle16(&q, 0x201); /* feature flags */
-        putle16(&q, 0);
-
-        putle16(&q, 0); /* reserved */
-        putle16(&q, 0);
-        putle16(&q, 0);
-        putle16(&q, 0);
-    }
-
-    /* isa bus */
-    putb(&q, 1); /* entry type = bus */
-    putb(&q, 0); /* bus ID */
-    putstr(&q, "ISA   ");
-    
-    /* ioapic */
-    ioapic_id = smp_cpus;
-    putb(&q, 2); /* entry type = I/O APIC */
-    putb(&q, ioapic_id); /* apic ID */
-    putb(&q, 0x11); /* I/O APIC version number */
-    putb(&q, 1); /* enable */
-    putle32(&q, 0xfec00000); /* I/O APIC addr */
-
-    /* irqs */
-    for(i = 0; i < 16; i++) {
-        putb(&q, 3); /* entry type = I/O interrupt */
-        putb(&q, 0); /* interrupt type = vectored interrupt */
-        putb(&q, 0); /* flags: po=0, el=0 */
-        putb(&q, 0);
-        putb(&q, 0); /* source bus ID = ISA */
-        putb(&q, i); /* source bus IRQ */
-        putb(&q, ioapic_id); /* dest I/O APIC ID */
-        putb(&q, i); /* dest I/O APIC interrupt in */
-    }
-    /* patch length */
-    len = q - mp_config_table;
-    mp_config_table[4] = len;
-    mp_config_table[5] = len >> 8;
-
-    mp_config_table[7] = -mpf_checksum(mp_config_table, q - mp_config_table);
-
-    /* align to 16 */
-    offset = q - bios_data;
-    offset = (offset + 15) & ~15;
-    float_pointer_struct = bios_data + offset;
-    
-    /* floating pointer structure */
-    q = float_pointer_struct;
-    putstr(&q, "_MP_");
-    /* pointer to MP config table */
-    putle32(&q, mp_config_table - bios_data + 0x000f0000); 
-
-    putb(&q, 1); /* length in 16 byte units */
-    putb(&q, 4); /* MP spec revision */
-    putb(&q, 0); /* checksum (patched later) */
-    putb(&q, 0); /* MP feature byte 1 */
-
-    putb(&q, 0);
-    putb(&q, 0);
-    putb(&q, 0);
-    putb(&q, 0);
-    float_pointer_struct[10] = 
-        -mpf_checksum(float_pointer_struct, q - float_pointer_struct);
-}
-#endif /* !CONFIG_DM */
-
-
 static const int ide_iobase[2] = { 0x1f0, 0x170 };
 static const int ide_iobase2[2] = { 0x3f6, 0x376 };
 static const int ide_irq[2] = { 14, 15 };
@@ -636,10 +470,10 @@ static void pc_init1(uint64_t ram_size, int vga_ram_size, char *boot_device,
 #ifndef NOBIOS
     char buf[1024];
     int ret, initrd_size;
-#endif
+#endif /* !NOBIOS */
     int linux_boot, i;
 #ifndef NOBIOS
-    unsigned long bios_offset, vga_bios_offset;
+    unsigned long bios_offset, vga_bios_offset, option_rom_offset;
     int bios_size, isa_bios_size;
 #endif /* !NOBIOS */
     PCIBus *pci_bus;
@@ -660,7 +494,7 @@ static void pc_init1(uint64_t ram_size, int vga_ram_size, char *boot_device,
             env->cpuid_features |= CPUID_APIC;
         }
 #endif /* !CONFIG_DM */
-        register_savevm("cpu", i, 3, cpu_save, cpu_load, env);
+        register_savevm("cpu", i, 4, cpu_save, cpu_load, env);
         qemu_register_reset(main_cpu_reset, env);
 #ifndef CONFIG_DM
         if (pci_enabled) {
@@ -692,9 +526,6 @@ static void pc_init1(uint64_t ram_size, int vga_ram_size, char *boot_device,
         fprintf(stderr, "qemu: could not load PC bios '%s'\n", buf);
         exit(1);
     }
-    if (bios_size == 65536) {
-        bios_add_mptable(phys_ram_base + bios_offset);
-    }
 
     /* VGA BIOS load */
     if (cirrus_vga_enabled) {
@@ -721,6 +552,23 @@ static void pc_init1(uint64_t ram_size, int vga_ram_size, char *boot_device,
     cpu_register_physical_memory(0x100000 - isa_bios_size, 
                                  isa_bios_size, 
                                  (bios_offset + bios_size - isa_bios_size) | IO_MEM_ROM);
+
+    option_rom_offset = 0;
+    for (i = 0; i < nb_option_roms; i++) {
+       int offset = bios_offset + bios_size + option_rom_offset;
+       int size;
+
+       size = load_image(option_rom[i], phys_ram_base + offset);
+       if ((size + option_rom_offset) > 0x10000) {
+           fprintf(stderr, "Too many option ROMS\n");
+           exit(1);
+       }
+       cpu_register_physical_memory(0xd0000 + option_rom_offset,
+                                    size, offset | IO_MEM_ROM);
+       option_rom_offset += size + 2047;
+       option_rom_offset -= (option_rom_offset % 2048);
+    }
+
     /* map all the bios at the top of memory */
     cpu_register_physical_memory((uint32_t)(-bios_size), 
                                  bios_size, bios_offset | IO_MEM_ROM);
@@ -787,8 +635,8 @@ static void pc_init1(uint64_t ram_size, int vga_ram_size, char *boot_device,
 #endif /* !CONFIG_DM */
 
     if (pci_enabled) {
-        pci_bus = i440fx_init();
-        piix3_devfn = piix3_init(pci_bus);
+        pci_bus = i440fx_init(&i440fx_state);
+        piix3_devfn = piix3_init(pci_bus, -1);
     } else {
         pci_bus = NULL;
     }
@@ -801,15 +649,20 @@ static void pc_init1(uint64_t ram_size, int vga_ram_size, char *boot_device,
     if (cirrus_vga_enabled) {
         if (pci_enabled) {
             pci_cirrus_vga_init(pci_bus, 
-                                ds, NULL, ram_size,
+                                ds, NULL, ram_size, 
                                 vga_ram_size);
         } else {
-            isa_cirrus_vga_init(ds, NULL, ram_size,
+            isa_cirrus_vga_init(ds, NULL, ram_size, 
                                 vga_ram_size);
         }
     } else {
-        vga_initialize(pci_bus, ds, NULL, ram_size,
-                       vga_ram_size, 0, 0);
+        if (pci_enabled) {
+            pci_vga_init(pci_bus, ds, NULL, ram_size, 
+                         vga_ram_size, 0, 0);
+        } else {
+            isa_vga_init(ds, NULL, ram_size, 
+                         vga_ram_size);
+        }
     }
 
     rtc_state = rtc_init(0x70, 8);
@@ -861,7 +714,7 @@ static void pc_init1(uint64_t ram_size, int vga_ram_size, char *boot_device,
         if (strcmp(nd->model, "ne2k_isa") == 0) {
             pc_init_ne2k_isa(nd);
         } else if (pci_enabled) {
-            pci_nic_init(pci_bus, nd);
+            pci_nic_init(pci_bus, nd, -1);
         } else {
             fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd->model);
             exit(1);
@@ -900,9 +753,18 @@ static void pc_init1(uint64_t ram_size, int vga_ram_size, char *boot_device,
 
 #ifndef CONFIG_DM
     if (pci_enabled && acpi_enabled) {
+        uint8_t *eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */
         piix4_pm_init(pci_bus, piix3_devfn + 3);
+        for (i = 0; i < 8; i++) {
+            SMBusDevice *eeprom = smbus_eeprom_device_init(0x50 + i,
+                eeprom_buf + (i * 256));
+            piix4_smbus_register_device(eeprom, 0x50 + i);
+        }
+    }
+    
+    if (i440fx_state) {
+        i440fx_init_memory_mappings(i440fx_state);
     }
-
 #if 0
     /* ??? Need to figure out some way for the user to
        specify SCSI devices.  */
@@ -932,15 +794,6 @@ static void pc_init1(uint64_t ram_size, int vga_ram_size, char *boot_device,
         }
     }
 #endif /* !CONFIG_DM */
-    /* must be done after all PCI devices are instanciated */
-    /* XXX: should be done in the Bochs BIOS */
-    if (pci_enabled) {
-        pci_bios_init();
-#ifndef CONFIG_DM
-        if (acpi_enabled)
-            acpi_bios_init();
-#endif /* !CONFIG_DM */
-    }
 }
 
 static void pc_init_pci(uint64_t ram_size, int vga_ram_size, char *boot_device,
index fd2dcc9d93089d12e33107f2062e20c15ec59f45..2d6ce60617c78161eb3c2de42332da55ed8d2df6 100644 (file)
@@ -29,49 +29,66 @@ struct PCIBus {
     int bus_num;
     int devfn_min;
     pci_set_irq_fn set_irq;
+    pci_map_irq_fn map_irq;
     uint32_t config_reg; /* XXX: suppress */
     /* low level pic */
     SetIRQFunc *low_set_irq;
     void *irq_opaque;
     PCIDevice *devices[256];
+    PCIDevice *parent_dev;
+    PCIBus *next;
+    /* The bus IRQ state is the logical OR of the connected devices.
+       Keep a count of the number of devices with raised IRQs.  */
+    int irq_count[];
 };
 
+static void pci_update_mappings(PCIDevice *d);
+
 target_phys_addr_t pci_mem_base;
 static int pci_irq_index;
 static PCIBus *first_bus;
 
-static void pci_update_mappings(PCIDevice *d);
-
-PCIBus *pci_register_bus(pci_set_irq_fn set_irq, void *pic, int devfn_min)
+PCIBus *pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
+                         void *pic, int devfn_min, int nirq)
 {
     PCIBus *bus;
-    bus = qemu_mallocz(sizeof(PCIBus));
+    bus = qemu_mallocz(sizeof(PCIBus) + (nirq * sizeof(int)));
     bus->set_irq = set_irq;
+    bus->map_irq = map_irq;
     bus->irq_opaque = pic;
     bus->devfn_min = devfn_min;
     first_bus = bus;
     return bus;
 }
 
+PCIBus *pci_register_secondary_bus(PCIDevice *dev, pci_map_irq_fn map_irq)
+{
+    PCIBus *bus;
+    bus = qemu_mallocz(sizeof(PCIBus));
+    bus->map_irq = map_irq;
+    bus->parent_dev = dev;
+    bus->next = dev->bus->next;
+    dev->bus->next = bus;
+    return bus;
+}
+
 int pci_bus_num(PCIBus *s)
 {
     return s->bus_num;
 }
 
-void generic_pci_save(QEMUFile* f, void *opaque)
+void pci_device_save(PCIDevice *s, QEMUFile *f)
 {
-    PCIDevice* s=(PCIDevice*)opaque;
-
+    qemu_put_be32(f, 1); /* PCI device version */
     qemu_put_buffer(f, s->config, 256);
 }
 
-int generic_pci_load(QEMUFile* f, void *opaque, int version_id)
+int pci_device_load(PCIDevice *s, QEMUFile *f)
 {
-    PCIDevice* s=(PCIDevice*)opaque;
-
+    uint32_t version_id;
+    version_id = qemu_get_be32(f);
     if (version_id != 1)
         return -EINVAL;
-
     qemu_get_buffer(f, s->config, 256);
     pci_update_mappings(s);
     return 0;
@@ -102,6 +119,7 @@ PCIDevice *pci_register_device(PCIBus *bus, const char *name,
     pci_dev->bus = bus;
     pci_dev->devfn = devfn;
     pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
+    memset(pci_dev->irq_state, 0, sizeof(pci_dev->irq_state));
 
     if (!config_read)
         config_read = pci_default_read_config;
@@ -224,16 +242,23 @@ uint32_t pci_default_read_config(PCIDevice *d,
                                  uint32_t address, int len)
 {
     uint32_t val;
+
     switch(len) {
-    case 1:
-        val = d->config[address];
-        break;
-    case 2:
-        val = le16_to_cpu(*(uint16_t *)(d->config + address));
-        break;
     default:
     case 4:
-        val = le32_to_cpu(*(uint32_t *)(d->config + address));
+       if (address <= 0xfc) {
+           val = le32_to_cpu(*(uint32_t *)(d->config + address));
+           break;
+       }
+       /* fall through */
+    case 2:
+        if (address <= 0xfe) {
+           val = le16_to_cpu(*(uint16_t *)(d->config + address));
+           break;
+       }
+       /* fall through */
+    case 1:
+        val = d->config[address];
         break;
     }
     return val;
@@ -336,7 +361,8 @@ void pci_default_write_config(PCIDevice *d,
 
             d->config[addr] = val;
         }
-        addr++;
+        if (++addr > 0xff)
+               break;
         val >>= 8;
     }
 
@@ -358,7 +384,9 @@ void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
            addr, val, len);
 #endif
     bus_num = (addr >> 16) & 0xff;
-    if (bus_num != 0)
+    while (s && s->bus_num != bus_num)
+        s = s->next;
+    if (!s)
         return;
     pci_dev = s->devices[(addr >> 8) & 0xff];
     if (!pci_dev)
@@ -379,7 +407,9 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
     uint32_t val;
 
     bus_num = (addr >> 16) & 0xff;
-    if (bus_num != 0)
+    while (s && s->bus_num != bus_num)
+        s= s->next;
+    if (!s)
         goto fail;
     pci_dev = s->devices[(addr >> 8) & 0xff];
     if (!pci_dev) {
@@ -418,8 +448,23 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
 /* 0 <= irq_num <= 3. level must be 0 or 1 */
 void pci_set_irq(PCIDevice *pci_dev, int irq_num, int level)
 {
-    PCIBus *bus = pci_dev->bus;
-    bus->set_irq(pci_dev, bus->irq_opaque, irq_num, level);
+    PCIBus *bus;
+    int change;
+    
+    change = level - pci_dev->irq_state[irq_num];
+    if (!change)
+        return;
+
+    pci_dev->irq_state[irq_num] = level;
+    for (;;) {
+        bus = pci_dev->bus;
+        irq_num = bus->map_irq(pci_dev, irq_num);
+        if (bus->set_irq)
+            break;
+        pci_dev = bus->parent_dev;
+    }
+    bus->irq_count[irq_num] += change;
+    bus->set_irq(bus->irq_opaque, irq_num, bus->irq_count[irq_num] != 0);
 }
 
 /***********************************************************/
@@ -432,6 +477,7 @@ typedef struct {
 
 static pci_class_desc pci_class_descriptions[] = 
 {
+    { 0x0100, "SCSI controller"},
     { 0x0101, "IDE controller"},
     { 0x0200, "Ethernet controller"},
     { 0x0300, "VGA controller"},
@@ -467,6 +513,9 @@ static void pci_info_device(PCIDevice *d)
     if (d->config[PCI_INTERRUPT_PIN] != 0) {
         term_printf("      IRQ %d.\n", d->config[PCI_INTERRUPT_LINE]);
     }
+    if (class == 0x0604) {
+        term_printf("      BUS %d.\n", d->config[0x19]);
+    }
     for(i = 0;i < PCI_NUM_REGIONS; i++) {
         r = &d->io_regions[i];
         if (r->size != 0) {
@@ -480,14 +529,19 @@ static void pci_info_device(PCIDevice *d)
             }
         }
     }
+    if (class == 0x0604 && d->config[0x19] != 0) {
+        pci_for_each_device(d->config[0x19], pci_info_device);
+    }
 }
 
-void pci_for_each_device(void (*fn)(PCIDevice *d))
+void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d))
 {
     PCIBus *bus = first_bus;
     PCIDevice *d;
     int devfn;
     
+    while (bus && bus->bus_num != bus_num)
+        bus = bus->next;
     if (bus) {
         for(devfn = 0; devfn < 256; devfn++) {
             d = bus->devices[devfn];
@@ -499,21 +553,68 @@ void pci_for_each_device(void (*fn)(PCIDevice *d))
 
 void pci_info(void)
 {
-    pci_for_each_device(pci_info_device);
+    pci_for_each_device(0, pci_info_device);
 }
 
 /* Initialize a PCI NIC.  */
-void pci_nic_init(PCIBus *bus, NICInfo *nd)
+void pci_nic_init(PCIBus *bus, NICInfo *nd, int devfn)
 {
     if (strcmp(nd->model, "ne2k_pci") == 0) {
-        pci_ne2000_init(bus, nd);
+        pci_ne2000_init(bus, nd, devfn);
     } else if (strcmp(nd->model, "rtl8139") == 0) {
-        pci_rtl8139_init(bus, nd);
+        pci_rtl8139_init(bus, nd, devfn);
     } else if (strcmp(nd->model, "pcnet") == 0) {
-        pci_pcnet_init(bus, nd);
+        pci_pcnet_init(bus, nd, devfn);
     } else {
         fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd->model);
         exit (1);
     }
 }
 
+typedef struct {
+    PCIDevice dev;
+    PCIBus *bus;
+} PCIBridge;
+
+void pci_bridge_write_config(PCIDevice *d, 
+                             uint32_t address, uint32_t val, int len)
+{
+    PCIBridge *s = (PCIBridge *)d;
+
+    if (address == 0x19 || (address == 0x18 && len > 1)) {
+        if (address == 0x19)
+            s->bus->bus_num = val & 0xff;
+        else
+            s->bus->bus_num = (val >> 8) & 0xff;
+#if defined(DEBUG_PCI)
+        printf ("pci-bridge: %s: Assigned bus %d\n", d->name, s->bus->bus_num);
+#endif
+    }
+    pci_default_write_config(d, address, val, len);
+}
+
+PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint32_t id,
+                        pci_map_irq_fn map_irq, const char *name)
+{
+    PCIBridge *s;
+    s = (PCIBridge *)pci_register_device(bus, name, sizeof(PCIBridge), 
+                                         devfn, NULL, pci_bridge_write_config);
+    s->dev.config[0x00] = id >> 16;
+    s->dev.config[0x01] = id > 24;
+    s->dev.config[0x02] = id; // device_id
+    s->dev.config[0x03] = id >> 8;
+    s->dev.config[0x04] = 0x06; // command = bus master, pci mem
+    s->dev.config[0x05] = 0x00;
+    s->dev.config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
+    s->dev.config[0x07] = 0x00; // status = fast devsel
+    s->dev.config[0x08] = 0x00; // revision
+    s->dev.config[0x09] = 0x00; // programming i/f
+    s->dev.config[0x0A] = 0x04; // class_sub = PCI to PCI bridge
+    s->dev.config[0x0B] = 0x06; // class_base = PCI_bridge
+    s->dev.config[0x0D] = 0x10; // latency_timer
+    s->dev.config[0x0E] = 0x81; // header_type
+    s->dev.config[0x1E] = 0xa0; // secondary status
+
+    s->bus = pci_register_secondary_bus(&s->dev, map_irq);
+    return s->bus;
+}
index 6e0b0ed58f232fd5e56148355cab845c013d64e4..6e68e238386494d81ef011b99e2417a00e405b50 100644 (file)
  * AMD Publication# 19436  Rev:E  Amendment/0  Issue Date: June 2000
  */
  
+/*
+ * On Sparc32, this is the Lance (Am7990) part of chip STP2000 (Master I/O), also
+ * produced as NCR89C100. See
+ * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C100.txt
+ * and
+ * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR92C990.txt
+ */
+
+/* TODO: remove little endian host assumptions */
 #include "vl.h"
 
 //#define PCNET_DEBUG
@@ -46,11 +56,12 @@ typedef struct PCNetState_st PCNetState;
 
 struct PCNetState_st {
     PCIDevice dev;
+    PCIDevice *pci_dev;
     VLANClientState *vc;
     NICInfo *nd;
     QEMUTimer *poll_timer;
-    int mmio_io_addr, rap, isr, lnkst;
-    target_phys_addr_t rdra, tdra;
+    int mmio_index, rap, isr, lnkst;
+    uint32_t rdra, tdra;
     uint8_t prom[16];
     uint16_t csr[128];
     uint16_t bcr[32];
@@ -58,6 +69,12 @@ struct PCNetState_st {
     int xmit_pos, recv_pos;
     uint8_t buffer[4096];
     int tx_busy;
+    void (*set_irq_cb)(void *s, int isr);
+    void (*phys_mem_read)(void *dma_opaque, target_phys_addr_t addr,
+                         uint8_t *buf, int len, int do_bswap);
+    void (*phys_mem_write)(void *dma_opaque, target_phys_addr_t addr,
+                          uint8_t *buf, int len, int do_bswap);
+    void *dma_opaque;
 };
 
 /* XXX: using bitfields for target memory structures is almost surely
@@ -99,6 +116,7 @@ struct qemu_ether_header {
 #define CSR_TXON(S)      !!(((S)->csr[0])&0x0010)
 #define CSR_RXON(S)      !!(((S)->csr[0])&0x0020)
 #define CSR_INEA(S)      !!(((S)->csr[0])&0x0040)
+#define CSR_BSWP(S)      !!(((S)->csr[3])&0x0004)
 #define CSR_LAPPEN(S)    !!(((S)->csr[3])&0x0020)
 #define CSR_DXSUFLO(S)   !!(((S)->csr[3])&0x0040)
 #define CSR_ASTRP_RCV(S) !!(((S)->csr[4])&0x0800)
@@ -147,35 +165,19 @@ struct qemu_ether_header {
 
 struct pcnet_initblk16 {
     uint16_t mode;
-    uint16_t padr1;
-    uint16_t padr2;
-    uint16_t padr3;
-    uint16_t ladrf1;
-    uint16_t ladrf2;
-    uint16_t ladrf3;
-    uint16_t ladrf4;
-    unsigned PACKED_FIELD(rdra:24);
-    unsigned PACKED_FIELD(res1:5);
-    unsigned PACKED_FIELD(rlen:3);
-    unsigned PACKED_FIELD(tdra:24);
-    unsigned PACKED_FIELD(res2:5);
-    unsigned PACKED_FIELD(tlen:3);
+    uint16_t padr[3];
+    uint16_t ladrf[4];
+    uint32_t rdra;
+    uint32_t tdra;
 };
 
 struct pcnet_initblk32 {
     uint16_t mode;
-    unsigned PACKED_FIELD(res1:4);
-    unsigned PACKED_FIELD(rlen:4);
-    unsigned PACKED_FIELD(res2:4);
-    unsigned PACKED_FIELD(tlen:4);
-    uint16_t padr1;
-    uint16_t padr2;
-    uint16_t padr3;
+    uint8_t rlen;
+    uint8_t tlen;
+    uint16_t padr[3];
     uint16_t _res;
-    uint16_t ladrf1;
-    uint16_t ladrf2;
-    uint16_t ladrf3;
-    uint16_t ladrf4;
+    uint16_t ladrf[4];
     uint32_t rdra;
     uint32_t tdra;
 };
@@ -251,112 +253,153 @@ struct pcnet_RMD {
         (R)->rmd2.rcc, (R)->rmd2.rpc, (R)->rmd2.mcnt,   \
         (R)->rmd2.zeros)
 
-static inline void pcnet_tmd_load(PCNetState *s, struct pcnet_TMD *tmd, target_phys_addr_t addr)
+static inline void pcnet_tmd_load(PCNetState *s, struct pcnet_TMD *tmd1, 
+                                  target_phys_addr_t addr)
 {
+    uint32_t *tmd = (uint32_t *)tmd1;
+
     if (!BCR_SWSTYLE(s)) {
         uint16_t xda[4];
-        cpu_physical_memory_read(addr,
-                (void *)&xda[0], sizeof(xda));
-        ((uint32_t *)tmd)[0] = (xda[0]&0xffff) |
-                ((xda[1]&0x00ff) << 16);
-        ((uint32_t *)tmd)[1] = (xda[2]&0xffff)|
-                ((xda[1] & 0xff00) << 16);
-        ((uint32_t *)tmd)[2] =
-                (xda[3] & 0xffff) << 16;
-        ((uint32_t *)tmd)[3] = 0;
-    }
-    else
-    if (BCR_SWSTYLE(s) != 3)
-        cpu_physical_memory_read(addr, (void *)tmd, 16);
-    else {
+        s->phys_mem_read(s->dma_opaque, addr,
+                (void *)&xda[0], sizeof(xda), 0);
+        le16_to_cpus(&xda[0]);
+        le16_to_cpus(&xda[1]);
+        le16_to_cpus(&xda[2]);
+        le16_to_cpus(&xda[3]);
+        tmd[0] = (xda[0]&0xffff) |
+            ((xda[1]&0x00ff) << 16);
+        tmd[1] = (xda[2]&0xffff)|
+            ((xda[1] & 0xff00) << 16);
+        tmd[2] =
+            (xda[3] & 0xffff) << 16;
+        tmd[3] = 0;
+    else {
         uint32_t xda[4];
-        cpu_physical_memory_read(addr,
-                (void *)&xda[0], sizeof(xda));
-        ((uint32_t *)tmd)[0] = xda[2];
-        ((uint32_t *)tmd)[1] = xda[1];
-        ((uint32_t *)tmd)[2] = xda[0];
-        ((uint32_t *)tmd)[3] = xda[3];
+        s->phys_mem_read(s->dma_opaque, addr,
+                (void *)&xda[0], sizeof(xda), 0);
+        le32_to_cpus(&xda[0]);
+        le32_to_cpus(&xda[1]);
+        le32_to_cpus(&xda[2]);
+        le32_to_cpus(&xda[3]);
+        if (BCR_SWSTYLE(s) != 3) {
+            memcpy(tmd, xda, sizeof(xda));
+        } else {
+            tmd[0] = xda[2];
+            tmd[1] = xda[1];
+            tmd[2] = xda[0];
+            tmd[3] = xda[3];
+        }
     }
 }
 
-static inline void pcnet_tmd_store(PCNetState *s, struct pcnet_TMD *tmd, target_phys_addr_t addr)
+static inline void pcnet_tmd_store(PCNetState *s, const struct pcnet_TMD *tmd1,
+                                   target_phys_addr_t addr)
 {
+    const uint32_t *tmd = (const uint32_t *)tmd1;
     if (!BCR_SWSTYLE(s)) {
         uint16_t xda[4];
-        xda[0] = ((uint32_t *)tmd)[0] & 0xffff;
-        xda[1] = ((((uint32_t *)tmd)[0]>>16)&0x00ff) |
-            ((((uint32_t *)tmd)[1]>>16)&0xff00);
-        xda[2] = ((uint32_t *)tmd)[1] & 0xffff;
-        xda[3] = ((uint32_t *)tmd)[2] >> 16;
-        cpu_physical_memory_write(addr,
-                (void *)&xda[0], sizeof(xda));
-    }
-    else {
-        if (BCR_SWSTYLE(s) != 3)
-            cpu_physical_memory_write(addr, (void *)tmd, 16);
-        else {
-            uint32_t xda[4];
-            xda[0] = ((uint32_t *)tmd)[2];
-            xda[1] = ((uint32_t *)tmd)[1];
-            xda[2] = ((uint32_t *)tmd)[0];
-            xda[3] = ((uint32_t *)tmd)[3];
-            cpu_physical_memory_write(addr,
-                    (void *)&xda[0], sizeof(xda));
+        xda[0] = tmd[0] & 0xffff;
+        xda[1] = ((tmd[0]>>16)&0x00ff) |
+            ((tmd[1]>>16)&0xff00);
+        xda[2] = tmd[1] & 0xffff;
+        xda[3] = tmd[2] >> 16;
+        cpu_to_le16s(&xda[0]);
+        cpu_to_le16s(&xda[1]);
+        cpu_to_le16s(&xda[2]);
+        cpu_to_le16s(&xda[3]);
+        s->phys_mem_write(s->dma_opaque, addr,
+                (void *)&xda[0], sizeof(xda), 0);
+    } else {
+        uint32_t xda[4];
+        if (BCR_SWSTYLE(s) != 3) {
+            memcpy(xda, tmd, sizeof(xda));
+        } else {
+            xda[0] = tmd[2];
+            xda[1] = tmd[1];
+            xda[2] = tmd[0];
+            xda[3] = tmd[3];
         }
+        cpu_to_le32s(&xda[0]);
+        cpu_to_le32s(&xda[1]);
+        cpu_to_le32s(&xda[2]);
+        cpu_to_le32s(&xda[3]);
+        s->phys_mem_write(s->dma_opaque, addr,
+                          (void *)&xda[0], sizeof(xda), 0);
     }
 }
 
-static inline void pcnet_rmd_load(PCNetState *s, struct pcnet_RMD *rmd, target_phys_addr_t addr)
+static inline void pcnet_rmd_load(PCNetState *s, struct pcnet_RMD *rmd1,
+                                  target_phys_addr_t addr)
 {
+    uint32_t *rmd = (uint32_t *)rmd1;
+
     if (!BCR_SWSTYLE(s)) {
         uint16_t rda[4];
-        cpu_physical_memory_read(addr,
-                (void *)&rda[0], sizeof(rda));
-        ((uint32_t *)rmd)[0] = (rda[0]&0xffff)|
-                ((rda[1] & 0x00ff) << 16);
-        ((uint32_t *)rmd)[1] = (rda[2]&0xffff)|
-                ((rda[1] & 0xff00) << 16);
-        ((uint32_t *)rmd)[2] = rda[3] & 0xffff;
-        ((uint32_t *)rmd)[3] = 0;
-    }
-    else
-    if (BCR_SWSTYLE(s) != 3)
-        cpu_physical_memory_read(addr, (void *)rmd, 16);
-    else {
+        s->phys_mem_read(s->dma_opaque, addr, 
+                         (void *)&rda[0], sizeof(rda), 0);
+        le16_to_cpus(&rda[0]);
+        le16_to_cpus(&rda[1]);
+        le16_to_cpus(&rda[2]);
+        le16_to_cpus(&rda[3]);
+        rmd[0] = (rda[0]&0xffff)|
+            ((rda[1] & 0x00ff) << 16);
+        rmd[1] = (rda[2]&0xffff)|
+            ((rda[1] & 0xff00) << 16);
+        rmd[2] = rda[3] & 0xffff;
+        rmd[3] = 0;
+    else {
         uint32_t rda[4];
-        cpu_physical_memory_read(addr,
-                (void *)&rda[0], sizeof(rda));
-        ((uint32_t *)rmd)[0] = rda[2];
-        ((uint32_t *)rmd)[1] = rda[1];
-        ((uint32_t *)rmd)[2] = rda[0];
-        ((uint32_t *)rmd)[3] = rda[3];
+        s->phys_mem_read(s->dma_opaque, addr, 
+                         (void *)&rda[0], sizeof(rda), 0);
+        le32_to_cpus(&rda[0]);
+        le32_to_cpus(&rda[1]);
+        le32_to_cpus(&rda[2]);
+        le32_to_cpus(&rda[3]);
+        if (BCR_SWSTYLE(s) != 3) {
+            memcpy(rmd, rda, sizeof(rda));
+        } else {
+            rmd[0] = rda[2];
+            rmd[1] = rda[1];
+            rmd[2] = rda[0];
+            rmd[3] = rda[3];
+        }
     }
 }
 
-static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd, target_phys_addr_t addr)
+static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd1, 
+                                   target_phys_addr_t addr)
 {
+    const uint32_t *rmd = (const uint32_t *)rmd1;
+
     if (!BCR_SWSTYLE(s)) {
-        uint16_t rda[4];                        \
-        rda[0] = ((uint32_t *)rmd)[0] & 0xffff; \
-        rda[1] = ((((uint32_t *)rmd)[0]>>16)&0xff)|\
-            ((((uint32_t *)rmd)[1]>>16)&0xff00);\
-        rda[2] = ((uint32_t *)rmd)[1] & 0xffff; \
-        rda[3] = ((uint32_t *)rmd)[2] & 0xffff; \
-        cpu_physical_memory_write(addr,         \
-                (void *)&rda[0], sizeof(rda));  \
-    }
-    else {
-        if (BCR_SWSTYLE(s) != 3)
-            cpu_physical_memory_write(addr, (void *)rmd, 16);
-        else {
-            uint32_t rda[4];
-            rda[0] = ((uint32_t *)rmd)[2];
-            rda[1] = ((uint32_t *)rmd)[1];
-            rda[2] = ((uint32_t *)rmd)[0];
-            rda[3] = ((uint32_t *)rmd)[3];
-            cpu_physical_memory_write(addr,
-                    (void *)&rda[0], sizeof(rda));
+        uint16_t rda[4];
+        rda[0] = rmd[0] & 0xffff;
+        rda[1] = ((rmd[0]>>16)&0xff)|
+            ((rmd[1]>>16)&0xff00);
+        rda[2] = rmd[1] & 0xffff;
+        rda[3] = rmd[2] & 0xffff;
+        cpu_to_le16s(&rda[0]);
+        cpu_to_le16s(&rda[1]);
+        cpu_to_le16s(&rda[2]);
+        cpu_to_le16s(&rda[3]);
+        s->phys_mem_write(s->dma_opaque, addr,
+                (void *)&rda[0], sizeof(rda), 0);
+    } else {
+        uint32_t rda[4];
+        if (BCR_SWSTYLE(s) != 3) {
+            memcpy(rda, rmd, sizeof(rda));
+        } else {
+            rda[0] = rmd[2];
+            rda[1] = rmd[1];
+            rda[2] = rmd[0];
+            rda[3] = rmd[3];
         }
+        cpu_to_le32s(&rda[0]);
+        cpu_to_le32s(&rda[1]);
+        cpu_to_le32s(&rda[2]);
+        cpu_to_le32s(&rda[3]);
+        s->phys_mem_write(s->dma_opaque, addr,
+                          (void *)&rda[0], sizeof(rda), 0);
     }
 }
 
@@ -391,8 +434,8 @@ static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd, target_
     case 0x00:                                  \
         do {                                    \
             uint16_t rda[4];                    \
-            cpu_physical_memory_read((ADDR),    \
-                (void *)&rda[0], sizeof(rda));  \
+            s->phys_mem_read(s->dma_opaque, (ADDR),    \
+                (void *)&rda[0], sizeof(rda), 0);  \
             (RES) |= (rda[2] & 0xf000)!=0xf000; \
             (RES) |= (rda[3] & 0xf000)!=0x0000; \
         } while (0);                            \
@@ -401,8 +444,8 @@ static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd, target_
     case 0x02:                                  \
         do {                                    \
             uint32_t rda[4];                    \
-            cpu_physical_memory_read((ADDR),    \
-                (void *)&rda[0], sizeof(rda)); \
+            s->phys_mem_read(s->dma_opaque, (ADDR),    \
+                (void *)&rda[0], sizeof(rda), 0); \
             (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \
             (RES) |= (rda[2] & 0x0000f000L)!=0x00000000L; \
         } while (0);                            \
@@ -410,8 +453,8 @@ static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd, target_
     case 0x03:                                  \
         do {                                    \
             uint32_t rda[4];                    \
-            cpu_physical_memory_read((ADDR),    \
-                (void *)&rda[0], sizeof(rda)); \
+            s->phys_mem_read(s->dma_opaque, (ADDR),    \
+                (void *)&rda[0], sizeof(rda), 0); \
             (RES) |= (rda[0] & 0x0000f000L)!=0x00000000L; \
             (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \
         } while (0);                            \
@@ -424,8 +467,8 @@ static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd, target_
     case 0x00:                                  \
         do {                                    \
             uint16_t xda[4];                    \
-            cpu_physical_memory_read((ADDR),    \
-                (void *)&xda[0], sizeof(xda));  \
+            s->phys_mem_read(s->dma_opaque, (ADDR),    \
+                (void *)&xda[0], sizeof(xda), 0);  \
             (RES) |= (xda[2] & 0xf000)!=0xf000;\
         } while (0);                            \
         break;                                  \
@@ -434,8 +477,8 @@ static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd, target_
     case 0x03:                                  \
         do {                                    \
             uint32_t xda[4];                    \
-            cpu_physical_memory_read((ADDR),    \
-                (void *)&xda[0], sizeof(xda));  \
+            s->phys_mem_read(s->dma_opaque, (ADDR),    \
+                (void *)&xda[0], sizeof(xda), 0);  \
             (RES) |= (xda[1] & 0x0000f000L)!=0x0000f000L; \
         } while (0);                            \
         break;                                  \
@@ -448,13 +491,12 @@ static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd, target_
     struct qemu_ether_header *hdr = (void *)(BUF);   \
     printf("packet dhost=%02x:%02x:%02x:%02x:%02x:%02x, "       \
            "shost=%02x:%02x:%02x:%02x:%02x:%02x, "              \
-           "type=0x%04x (bcast=%d)\n",                          \
+           "type=0x%04x\n",                          \
            hdr->ether_dhost[0],hdr->ether_dhost[1],hdr->ether_dhost[2], \
            hdr->ether_dhost[3],hdr->ether_dhost[4],hdr->ether_dhost[5], \
            hdr->ether_shost[0],hdr->ether_shost[1],hdr->ether_shost[2], \
            hdr->ether_shost[3],hdr->ether_shost[4],hdr->ether_shost[5], \
-           be16_to_cpu(hdr->ether_type),                                \
-           !!ETHER_IS_MULTICAST(hdr->ether_dhost));                     \
+           be16_to_cpu(hdr->ether_type));                     \
 } while (0)
 
 #define MULTICAST_FILTER_LEN 8
@@ -571,7 +613,7 @@ static inline int padr_match(PCNetState *s, const uint8_t *buf, int size)
 
 static inline int padr_bcast(PCNetState *s, const uint8_t *buf, int size)
 {
-    static uint8_t BCAST[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+    static const uint8_t BCAST[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
     struct qemu_ether_header *hdr = (void *)buf;
     int result = !CSR_DRCVBC(s) && !memcmp(hdr->ether_dhost, BCAST, 6);
 #ifdef PCNET_DEBUG_MATCH
@@ -721,51 +763,65 @@ static void pcnet_update_irq(PCNetState *s)
         printf("pcnet: INTA=%d\n", isr);
 #endif
     }
-        pci_set_irq(&s->dev, 0, isr);
-        s->isr = isr;
+    s->set_irq_cb(s, isr);
+    s->isr = isr;
 }
 
 static void pcnet_init(PCNetState *s)
 {
+    int rlen, tlen;
+    uint16_t *padr, *ladrf, mode;
+    uint32_t rdra, tdra;
+
 #ifdef PCNET_DEBUG
     printf("pcnet_init init_addr=0x%08x\n", PHYSADDR(s,CSR_IADR(s)));
 #endif
     
-#define PCNET_INIT() do { \
-        cpu_physical_memory_read(PHYSADDR(s,CSR_IADR(s)),       \
-                (uint8_t *)&initblk, sizeof(initblk));          \
-        s->csr[15] = le16_to_cpu(initblk.mode);                 \
-        CSR_RCVRL(s) = (initblk.rlen < 9) ? (1 << initblk.rlen) : 512;  \
-        CSR_XMTRL(s) = (initblk.tlen < 9) ? (1 << initblk.tlen) : 512;  \
-        s->csr[ 6] = (initblk.tlen << 12) | (initblk.rlen << 8);        \
-        s->csr[ 8] = le16_to_cpu(initblk.ladrf1);                       \
-        s->csr[ 9] = le16_to_cpu(initblk.ladrf2);                       \
-        s->csr[10] = le16_to_cpu(initblk.ladrf3);                       \
-        s->csr[11] = le16_to_cpu(initblk.ladrf4);                       \
-        s->csr[12] = le16_to_cpu(initblk.padr1);                        \
-        s->csr[13] = le16_to_cpu(initblk.padr2);                        \
-        s->csr[14] = le16_to_cpu(initblk.padr3);                        \
-        s->rdra = PHYSADDR(s,initblk.rdra);                             \
-        s->tdra = PHYSADDR(s,initblk.tdra);                             \
-} while (0)
-    
     if (BCR_SSIZE32(s)) {
         struct pcnet_initblk32 initblk;
-        PCNET_INIT();
-#ifdef PCNET_DEBUG
-        printf("initblk.rlen=0x%02x, initblk.tlen=0x%02x\n",
-                initblk.rlen, initblk.tlen);
-#endif
+        s->phys_mem_read(s->dma_opaque, PHYSADDR(s,CSR_IADR(s)),
+                (uint8_t *)&initblk, sizeof(initblk), 0);
+        mode = initblk.mode;
+        rlen = initblk.rlen >> 4;
+        tlen = initblk.tlen >> 4;
+        ladrf = initblk.ladrf;
+        padr = initblk.padr;
+        rdra = le32_to_cpu(initblk.rdra);
+        tdra = le32_to_cpu(initblk.tdra);
+        s->rdra = PHYSADDR(s,initblk.rdra);
+        s->tdra = PHYSADDR(s,initblk.tdra);
     } else {
         struct pcnet_initblk16 initblk;
-        PCNET_INIT();
-#ifdef PCNET_DEBUG
-        printf("initblk.rlen=0x%02x, initblk.tlen=0x%02x\n",
-                initblk.rlen, initblk.tlen);
-#endif
+        s->phys_mem_read(s->dma_opaque, PHYSADDR(s,CSR_IADR(s)),
+                (uint8_t *)&initblk, sizeof(initblk), 0);
+        mode = initblk.mode;
+        ladrf = initblk.ladrf;
+        padr = initblk.padr;
+        rdra = le32_to_cpu(initblk.rdra);
+        tdra = le32_to_cpu(initblk.tdra);
+        rlen = rdra >> 29;
+        tlen = tdra >> 29;
+        rdra &= 0x00ffffff;
+        tdra &= 0x00ffffff;
     }
-
-#undef PCNET_INIT
+    
+#if defined(PCNET_DEBUG)
+    printf("rlen=%d tlen=%d\n",
+           rlen, tlen);
+#endif
+    CSR_RCVRL(s) = (rlen < 9) ? (1 << rlen) : 512;
+    CSR_XMTRL(s) = (tlen < 9) ? (1 << tlen) : 512;
+    s->csr[ 6] = (tlen << 12) | (rlen << 8);
+    s->csr[15] = le16_to_cpu(mode);
+    s->csr[ 8] = le16_to_cpu(ladrf[0]);
+    s->csr[ 9] = le16_to_cpu(ladrf[1]);
+    s->csr[10] = le16_to_cpu(ladrf[2]);
+    s->csr[11] = le16_to_cpu(ladrf[3]);
+    s->csr[12] = le16_to_cpu(padr[0]);
+    s->csr[13] = le16_to_cpu(padr[1]);
+    s->csr[14] = le16_to_cpu(padr[2]);
+    s->rdra = PHYSADDR(s, rdra);
+    s->tdra = PHYSADDR(s, tdra);
 
     CSR_RCVRC(s) = CSR_RCVRL(s);
     CSR_XMTRC(s) = CSR_XMTRL(s);
@@ -1035,7 +1091,7 @@ static void pcnet_receive(void *opaque, const uint8_t *buf, int size)
 #define PCNET_RECV_STORE() do {                                 \
     int count = MIN(4096 - rmd.rmd1.bcnt,size);                 \
     target_phys_addr_t rbadr = PHYSADDR(s, rmd.rmd0.rbadr);     \
-    cpu_physical_memory_write(rbadr, src, count);               \
+    s->phys_mem_write(s->dma_opaque, rbadr, src, count, CSR_BSWP(s));  \
     src += count; size -= count;                                \
     rmd.rmd2.mcnt = count; rmd.rmd1.own = 0;                    \
     RMDSTORE(&rmd, PHYSADDR(s,crda));                           \
@@ -1125,15 +1181,17 @@ static void pcnet_transmit(PCNetState *s)
         if (tmd.tmd1.stp) {
             s->xmit_pos = 0;                
             if (!tmd.tmd1.enp) {
-                cpu_physical_memory_read(PHYSADDR(s, tmd.tmd0.tbadr),
-                        s->buffer, 4096 - tmd.tmd1.bcnt);
+                s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tmd0.tbadr),
+                                 s->buffer, 4096 - tmd.tmd1.bcnt, 
+                                 CSR_BSWP(s));
                 s->xmit_pos += 4096 - tmd.tmd1.bcnt;
             } 
             xmit_cxda = PHYSADDR(s,CSR_CXDA(s));
         }
         if (tmd.tmd1.enp && (s->xmit_pos >= 0)) {
-            cpu_physical_memory_read(PHYSADDR(s, tmd.tmd0.tbadr),
-                    s->buffer + s->xmit_pos, 4096 - tmd.tmd1.bcnt);
+            s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tmd0.tbadr),
+                             s->buffer + s->xmit_pos, 4096 - tmd.tmd1.bcnt, 
+                             CSR_BSWP(s));
             s->xmit_pos += 4096 - tmd.tmd1.bcnt;
 #ifdef PCNET_DEBUG
             printf("pcnet_transmit size=%d\n", s->xmit_pos);
@@ -1426,8 +1484,9 @@ static uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap)
     return val;
 }
 
-static void pcnet_h_reset(PCNetState *s)
+void pcnet_h_reset(void *opaque)
 {
+    PCNetState *s = opaque;
     int i;
     uint16_t checksum;
 
@@ -1703,36 +1762,14 @@ static uint32_t pcnet_mmio_readl(void *opaque, target_phys_addr_t addr)
 }
 
 
-static CPUWriteMemoryFunc *pcnet_mmio_write[] = {
-    (CPUWriteMemoryFunc *)&pcnet_mmio_writeb,
-    (CPUWriteMemoryFunc *)&pcnet_mmio_writew,
-    (CPUWriteMemoryFunc *)&pcnet_mmio_writel
-};
-
-static CPUReadMemoryFunc *pcnet_mmio_read[] = {
-    (CPUReadMemoryFunc *)&pcnet_mmio_readb,
-    (CPUReadMemoryFunc *)&pcnet_mmio_readw,
-    (CPUReadMemoryFunc *)&pcnet_mmio_readl
-};
-
-static void pcnet_mmio_map(PCIDevice *pci_dev, int region_num, 
-                            uint32_t addr, uint32_t size, int type)
-{
-    PCNetState *d = (PCNetState *)pci_dev;
-
-#ifdef PCNET_DEBUG_IO
-    printf("pcnet_ioport_map addr=0x%08x 0x%08x\n", addr, size);
-#endif
-
-    cpu_register_physical_memory(addr, PCNET_PNPMMIO_SIZE, d->mmio_io_addr);
-}
-
-
 static void pcnet_save(QEMUFile *f, void *opaque)
 {
     PCNetState *s = opaque;
     unsigned int i;
 
+    if (s->pci_dev)
+        pci_device_save(s->pci_dev, f);
+
     qemu_put_be32s(f, &s->rap);
     qemu_put_be32s(f, &s->isr);
     qemu_put_be32s(f, &s->lnkst);
@@ -1756,9 +1793,15 @@ static int pcnet_load(QEMUFile *f, void *opaque, int version_id)
     PCNetState *s = opaque;
     int i, ret;
 
-    if (version_id != 1)
+    if (version_id != 2)
         return -EINVAL;
 
+    if (s->pci_dev) {
+        ret = pci_device_load(s->pci_dev, f);
+        if (ret < 0)
+            return ret;
+    }
+
     qemu_get_be32s(f, &s->rap);
     qemu_get_be32s(f, &s->isr);
     qemu_get_be32s(f, &s->lnkst);
@@ -1779,11 +1822,81 @@ static int pcnet_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-void pci_pcnet_init(PCIBus *bus, NICInfo *nd)
+static void pcnet_common_init(PCNetState *d, NICInfo *nd, const char *info_str)
+{
+    int instance;
+
+    d->poll_timer = qemu_new_timer(vm_clock, pcnet_poll_timer, d);
+
+    d->nd = nd;
+
+    d->vc = qemu_new_vlan_client(nd->vlan, pcnet_receive, 
+                                 pcnet_can_receive, d);
+
+    snprintf(d->vc->info_str, sizeof(d->vc->info_str),
+             "pcnet macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
+             d->nd->macaddr[0],
+             d->nd->macaddr[1],
+             d->nd->macaddr[2],
+             d->nd->macaddr[3],
+             d->nd->macaddr[4],
+             d->nd->macaddr[5]);
+
+    pcnet_h_reset(d);
+
+    instance = pci_bus_num(d->dev.bus) << 8 | d->dev.devfn;
+    register_savevm("pcnet", instance, 2, pcnet_save, pcnet_load, d);
+}
+
+/* PCI interface */
+
+static CPUWriteMemoryFunc *pcnet_mmio_write[] = {
+    (CPUWriteMemoryFunc *)&pcnet_mmio_writeb,
+    (CPUWriteMemoryFunc *)&pcnet_mmio_writew,
+    (CPUWriteMemoryFunc *)&pcnet_mmio_writel
+};
+
+static CPUReadMemoryFunc *pcnet_mmio_read[] = {
+    (CPUReadMemoryFunc *)&pcnet_mmio_readb,
+    (CPUReadMemoryFunc *)&pcnet_mmio_readw,
+    (CPUReadMemoryFunc *)&pcnet_mmio_readl
+};
+
+static void pcnet_mmio_map(PCIDevice *pci_dev, int region_num, 
+                            uint32_t addr, uint32_t size, int type)
+{
+    PCNetState *d = (PCNetState *)pci_dev;
+
+#ifdef PCNET_DEBUG_IO
+    printf("pcnet_ioport_map addr=0x%08x 0x%08x\n", addr, size);
+#endif
+
+    cpu_register_physical_memory(addr, PCNET_PNPMMIO_SIZE, d->mmio_index);
+}
+
+static void pcnet_pci_set_irq_cb(void *opaque, int isr)
+{
+    PCNetState *s = opaque;
+
+    pci_set_irq(&s->dev, 0, isr);
+}
+
+static void pci_physical_memory_write(void *dma_opaque, target_phys_addr_t addr,
+                                      uint8_t *buf, int len, int do_bswap)
+{
+    cpu_physical_memory_write(addr, buf, len);
+}
+
+static void pci_physical_memory_read(void *dma_opaque, target_phys_addr_t addr,
+                                     uint8_t *buf, int len, int do_bswap)
+{
+    cpu_physical_memory_read(addr, buf, len);
+}
+
+void pci_pcnet_init(PCIBus *bus, NICInfo *nd, int devfn)
 {
     PCNetState *d;
     uint8_t *pci_conf;
-    int instance;
 
 #if 0
     printf("sizeof(RMD)=%d, sizeof(TMD)=%d\n", 
@@ -1791,7 +1904,7 @@ void pci_pcnet_init(PCIBus *bus, NICInfo *nd)
 #endif
 
     d = (PCNetState *)pci_register_device(bus, "PCNet", sizeof(PCNetState),
-                                          -1, NULL, NULL);
+                                          devfn, NULL, NULL);
                                           
     pci_conf = d->dev.config;
     
@@ -1813,7 +1926,7 @@ void pci_pcnet_init(PCIBus *bus, NICInfo *nd)
     pci_conf[0x3f] = 0xff;
 
     /* Handler for memory-mapped I/O */
-    d->mmio_io_addr =
+    d->mmio_index =
       cpu_register_io_memory(0, pcnet_mmio_read, pcnet_mmio_write, d);
 
     pci_register_io_region((PCIDevice *)d, 0, PCNET_IOPORT_SIZE, 
@@ -1822,26 +1935,58 @@ void pci_pcnet_init(PCIBus *bus, NICInfo *nd)
     pci_register_io_region((PCIDevice *)d, 1, PCNET_PNPMMIO_SIZE, 
                            PCI_ADDRESS_SPACE_MEM, pcnet_mmio_map);
                            
-    d->poll_timer = qemu_new_timer(vm_clock, pcnet_poll_timer, d);
+    d->set_irq_cb = pcnet_pci_set_irq_cb;
+    d->phys_mem_read = pci_physical_memory_read;
+    d->phys_mem_write = pci_physical_memory_write;
+    d->pci_dev = &d->dev;
 
-    d->nd = nd;
+    pcnet_common_init(d, nd, "pcnet");
+}
 
-    d->vc = qemu_new_vlan_client(nd->vlan, pcnet_receive, 
-                                 pcnet_can_receive, d);
+/* SPARC32 interface */
 
-    instance = pci_bus_num(bus) << 8 | d->dev.devfn;
-    register_savevm("pcnet", instance, 1, pcnet_save, pcnet_load, d);
-    register_savevm("pcnet_pci", instance, 1, generic_pci_save,
-                    generic_pci_load, &d->dev);
-    
-    snprintf(d->vc->info_str, sizeof(d->vc->info_str),
-             "pcnet macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
-             d->nd->macaddr[0],
-             d->nd->macaddr[1],
-             d->nd->macaddr[2],
-             d->nd->macaddr[3],
-             d->nd->macaddr[4],
-             d->nd->macaddr[5]);
+#if defined (TARGET_SPARC) && !defined(TARGET_SPARC64) // Avoid compile failure
 
-    pcnet_h_reset(d);
+static CPUReadMemoryFunc *lance_mem_read[3] = {
+    (CPUReadMemoryFunc *)&pcnet_ioport_readw,
+    (CPUReadMemoryFunc *)&pcnet_ioport_readw,
+    (CPUReadMemoryFunc *)&pcnet_ioport_readw,
+};
+
+static CPUWriteMemoryFunc *lance_mem_write[3] = {
+    (CPUWriteMemoryFunc *)&pcnet_ioport_writew,
+    (CPUWriteMemoryFunc *)&pcnet_ioport_writew,
+    (CPUWriteMemoryFunc *)&pcnet_ioport_writew,
+};
+
+static void pcnet_sparc_set_irq_cb(void *opaque, int isr)
+{
+    PCNetState *s = opaque;
+
+    ledma_set_irq(s->dma_opaque, isr);
+}
+
+void *lance_init(NICInfo *nd, uint32_t leaddr, void *dma_opaque)
+{
+    PCNetState *d;
+    int lance_io_memory;
+
+    d = qemu_mallocz(sizeof(PCNetState));
+    if (!d)
+        return NULL;
+
+    lance_io_memory =
+        cpu_register_io_memory(0, lance_mem_read, lance_mem_write, d);
+
+    d->dma_opaque = dma_opaque;
+    cpu_register_physical_memory(leaddr, 4, lance_io_memory);
+
+    d->set_irq_cb = pcnet_sparc_set_irq_cb;
+    d->phys_mem_read = ledma_memory_read;
+    d->phys_mem_write = ledma_memory_write;
+
+    pcnet_common_init(d, nd, "lance");
+
+    return d;
 }
+#endif /* TARGET_SPARC */
index ee2f63a1a0dcd8c41e84ea1f683839c6035175d4..0db8b564543473707a1034c3be5532affa5e9b2a 100644 (file)
@@ -135,7 +135,6 @@ static uint32_t pflash_read (pflash_t *pfl, target_ulong offset, int width)
 #else
             ret = p[offset];
             ret |= p[offset + 1] << 8;
-            ret |= p[offset + 1] << 8;
             ret |= p[offset + 2] << 16;
             ret |= p[offset + 3] << 24;
 #endif
index 731ba83f8006198b5228b1302330f9f1c241df68..d8d56ec0a8672b1dcbd39149733399b24add7eb8 100644 (file)
@@ -60,15 +60,21 @@ typedef struct PCIAcpiState {
 static void piix4acpi_save(QEMUFile *f, void *opaque)
 {
     PCIAcpiState *s = opaque;
+    pci_device_save(&s->dev, f);
     qemu_put_be16s(f, &s->pm1_control);
 }
 
 static int piix4acpi_load(QEMUFile *f, void *opaque, int version_id)
 {
     PCIAcpiState *s = opaque;
+    int ret;
     if (version_id > 1) 
         return -EINVAL;
+    ret = pci_device_load(&s->dev, f);
+    if (ret < 0)
+       return ret;
     qemu_get_be16s(f, &s->pm1_control);
+    return 0;
 }
 
 static void acpiPm1Control_writeb(void *opaque, uint32_t addr, uint32_t val)
@@ -206,9 +212,7 @@ void pci_piix4_acpi_init(PCIBus *bus, int devfn)
     pci_conf[0x43] = 0x00;
     d->pm1_control = SCI_EN;
 
-    acpi_map(d, 0, 0x1f40, 0x10, PCI_ADDRESS_SPACE_IO);
+    acpi_map((PCIDevice *)d, 0, 0x1f40, 0x10, PCI_ADDRESS_SPACE_IO);
 
-    register_savevm("piix4acpi", 0, 1, piix4acpi_save, piix4acpi_load, d);    
-    register_savevm("piix4acpi_pci", 0, 1, generic_pci_save, generic_pci_load, 
-                    &d->dev);
+    register_savevm("piix4acpi", 0, 1, piix4acpi_save, piix4acpi_load, d);
 }
index 497d66898ca88a84158e2b2e8125908fb84bc437..1b16652bc0d9ad2eaa3b3a7920fb3ef1b3d570a0 100644 (file)
@@ -40,16 +40,129 @@ static uint32_t i440fx_addr_readl(void* opaque, uint32_t addr)
     return s->config_reg;
 }
 
-static void piix3_set_irq(PCIDevice *pci_dev, void *pic, int irq_num, int level);
+static void piix3_set_irq(void *pic, int irq_num, int level);
 
-PCIBus *i440fx_init(void)
+/* return the global irq number corresponding to a given device irq
+   pin. We could also use the bus number to have a more precise
+   mapping. */
+static int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
+{
+    int slot_addend;
+    slot_addend = (pci_dev->devfn >> 3) - 1;
+    return (irq_num + slot_addend) & 3;
+}
+
+static uint32_t isa_page_descs[384 / 4];
+static uint8_t smm_enabled;
+
+static void update_pam(PCIDevice *d, uint32_t start, uint32_t end, int r)
+{
+    uint32_t addr;
+
+    //    printf("ISA mapping %08x-0x%08x: %d\n", start, end, r);
+    switch(r) {
+    case 3:
+        /* RAM */
+        cpu_register_physical_memory(start, end - start, 
+                                     start);
+        break;
+    case 1:
+        /* ROM (XXX: not quite correct) */
+        cpu_register_physical_memory(start, end - start, 
+                                     start | IO_MEM_ROM);
+        break;
+    case 2:
+    case 0:
+        /* XXX: should distinguish read/write cases */
+        for(addr = start; addr < end; addr += 4096) {
+            cpu_register_physical_memory(addr, 4096, 
+                                         isa_page_descs[(addr - 0xa0000) >> 12]);
+        }
+        break;
+    }
+}
+
+static void i440fx_update_memory_mappings(PCIDevice *d)
+{
+    int i, r;
+    uint32_t smram, addr;
+
+    update_pam(d, 0xf0000, 0x100000, (d->config[0x59] >> 4) & 3);
+    for(i = 0; i < 12; i++) {
+        r = (d->config[(i >> 1) + 0x5a] >> ((i & 1) * 4)) & 3;
+        update_pam(d, 0xc0000 + 0x4000 * i, 0xc0000 + 0x4000 * (i + 1), r);
+    }
+    smram = d->config[0x72];
+    if ((smm_enabled && (smram & 0x08)) || (smram & 0x40)) {
+        cpu_register_physical_memory(0xa0000, 0x20000, 0xa0000);
+    } else {
+        for(addr = 0xa0000; addr < 0xc0000; addr += 4096) {
+            cpu_register_physical_memory(addr, 4096, 
+                                         isa_page_descs[(addr - 0xa0000) >> 12]);
+        }
+    }
+}
+
+void i440fx_set_smm(PCIDevice *d, int val)
+{
+    val = (val != 0);
+    if (smm_enabled != val) {
+        smm_enabled = val;
+        i440fx_update_memory_mappings(d);
+    }
+}
+
+
+/* XXX: suppress when better memory API. We make the assumption that
+   no device (in particular the VGA) changes the memory mappings in
+   the 0xa0000-0x100000 range */
+void i440fx_init_memory_mappings(PCIDevice *d)
+{
+    int i;
+    for(i = 0; i < 96; i++) {
+        isa_page_descs[i] = cpu_get_physical_page_desc(0xa0000 + i * 0x1000);
+    }
+}
+
+static void i440fx_write_config(PCIDevice *d, 
+                                uint32_t address, uint32_t val, int len)
+{
+    /* XXX: implement SMRAM.D_LOCK */
+    pci_default_write_config(d, address, val, len);
+    if ((address >= 0x59 && address <= 0x5f) || address == 0x72)
+        i440fx_update_memory_mappings(d);
+}
+
+static void i440fx_save(QEMUFile* f, void *opaque)
+{
+    PCIDevice *d = opaque;
+    pci_device_save(d, f);
+    qemu_put_8s(f, &smm_enabled);
+}
+
+static int i440fx_load(QEMUFile* f, void *opaque, int version_id)
+{
+    PCIDevice *d = opaque;
+    int ret;
+
+    if (version_id != 1)
+        return -EINVAL;
+    ret = pci_device_load(d, f);
+    if (ret < 0)
+        return ret;
+    i440fx_update_memory_mappings(d);
+    qemu_get_8s(f, &smm_enabled);
+    return 0;
+}
+
+PCIBus *i440fx_init(PCIDevice **pi440fx_state)
 {
     PCIBus *b;
     PCIDevice *d;
     I440FXState *s;
 
     s = qemu_mallocz(sizeof(I440FXState));
-    b = pci_register_bus(piix3_set_irq, NULL, 0);
+    b = pci_register_bus(piix3_set_irq, pci_slot_get_pirq, NULL, 0, 4);
     s->bus = b;
 
     register_ioport_write(0xcf8, 4, 4, i440fx_addr_writel, s);
@@ -63,7 +176,7 @@ PCIBus *i440fx_init(void)
     register_ioport_read(0xcfc, 4, 4, pci_host_data_readl, s);
 
     d = pci_register_device(b, "i440FX", sizeof(PCIDevice), 0, 
-                            NULL, NULL);
+                            NULL, i440fx_write_config);
 
     d->config[0x00] = 0x86; // vendor_id
     d->config[0x01] = 0x80;
@@ -73,75 +186,41 @@ PCIBus *i440fx_init(void)
     d->config[0x0a] = 0x00; // class_sub = host2pci
     d->config[0x0b] = 0x06; // class_base = PCI_bridge
     d->config[0x0e] = 0x00; // header_type
+
+    d->config[0x72] = 0x02; /* SMRAM */
+
+    register_savevm("I440FX", 0, 1, i440fx_save, i440fx_load, d);
+    *pi440fx_state = d;
     return b;
 }
 
 /* PIIX3 PCI to ISA bridge */
 
-static PCIDevice *piix3_dev;
+PCIDevice *piix3_dev;
+PCIDevice *piix4_dev;
 
 /* just used for simpler irq handling. */
 #define PCI_IRQ_WORDS   ((PCI_DEVICES_MAX + 31) / 32)
 
-static uint32_t pci_irq_levels[4][PCI_IRQ_WORDS];
+static int pci_irq_levels[4];
 
-/* return the global irq number corresponding to a given device irq
-   pin. We could also use the bus number to have a more precise
-   mapping. */
-static inline int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
-{
-    int slot_addend;
-    slot_addend = (pci_dev->devfn >> 3) - 1;
-    return (irq_num + slot_addend) & 3;
-}
-
-static inline int get_pci_irq_level(int irq_num)
-{
-    int pic_level;
-#if (PCI_IRQ_WORDS == 2)
-    pic_level = ((pci_irq_levels[irq_num][0] | 
-                  pci_irq_levels[irq_num][1]) != 0);
-#else
-    {
-        int i;
-        pic_level = 0;
-        for(i = 0; i < PCI_IRQ_WORDS; i++) {
-            if (pci_irq_levels[irq_num][i]) {
-                pic_level = 1;
-                break;
-            }
-        }
-    }
-#endif
-    return pic_level;
-}
-
-static void piix3_set_irq(PCIDevice *pci_dev, void *pic, int irq_num, int level)
+static void piix3_set_irq(void *pic, int irq_num, int level)
 {
-    int irq_index, shift, pic_irq, pic_level;
-    uint32_t *p;
+    int i, pic_irq, pic_level;
 
-    irq_num = pci_slot_get_pirq(pci_dev, irq_num);
-    irq_index = pci_dev->irq_index;
-    p = &pci_irq_levels[irq_num][irq_index >> 5];
-    shift = (irq_index & 0x1f);
-    *p = (*p & ~(1 << shift)) | (level << shift);
+    pci_irq_levels[irq_num] = level;
 
     /* now we change the pic irq level according to the piix irq mappings */
     /* XXX: optimize */
     pic_irq = piix3_dev->config[0x60 + irq_num];
     if (pic_irq < 16) {
-        /* the pic level is the logical OR of all the PCI irqs mapped
+        /* The pic level is the logical OR of all the PCI irqs mapped
            to it */
         pic_level = 0;
-        if (pic_irq == piix3_dev->config[0x60])
-            pic_level |= get_pci_irq_level(0);
-        if (pic_irq == piix3_dev->config[0x61])
-            pic_level |= get_pci_irq_level(1);
-        if (pic_irq == piix3_dev->config[0x62])
-            pic_level |= get_pci_irq_level(2);
-        if (pic_irq == piix3_dev->config[0x63])
-            pic_level |= get_pci_irq_level(3);
+        for (i = 0; i < 4; i++) {
+            if (pic_irq == piix3_dev->config[0x60 + i])
+                pic_level |= pci_irq_levels[i];
+        }
         pic_set_irq(pic_irq, pic_level);
     }
 }
@@ -167,6 +246,42 @@ static void piix3_reset(PCIDevice *d)
     pci_conf[0x80] = 0x00;
     pci_conf[0x82] = 0x00;
     pci_conf[0xa0] = 0x08;
+    pci_conf[0xa2] = 0x00;
+    pci_conf[0xa3] = 0x00;
+    pci_conf[0xa4] = 0x00;
+    pci_conf[0xa5] = 0x00;
+    pci_conf[0xa6] = 0x00;
+    pci_conf[0xa7] = 0x00;
+    pci_conf[0xa8] = 0x0f;
+    pci_conf[0xaa] = 0x00;
+    pci_conf[0xab] = 0x00;
+    pci_conf[0xac] = 0x00;
+    pci_conf[0xae] = 0x00;
+}
+
+static void piix4_reset(PCIDevice *d)
+{
+    uint8_t *pci_conf = d->config;
+
+    pci_conf[0x04] = 0x07; // master, memory and I/O
+    pci_conf[0x05] = 0x00;
+    pci_conf[0x06] = 0x00;
+    pci_conf[0x07] = 0x02; // PCI_status_devsel_medium
+    pci_conf[0x4c] = 0x4d;
+    pci_conf[0x4e] = 0x03;
+    pci_conf[0x4f] = 0x00;
+    pci_conf[0x60] = 0x0a; // PCI A -> IRQ 10
+    pci_conf[0x61] = 0x0a; // PCI B -> IRQ 10
+    pci_conf[0x62] = 0x0b; // PCI C -> IRQ 11
+    pci_conf[0x63] = 0x0b; // PCI D -> IRQ 11
+    pci_conf[0x69] = 0x02;
+    pci_conf[0x70] = 0x80;
+    pci_conf[0x76] = 0x0c;
+    pci_conf[0x77] = 0x0c;
+    pci_conf[0x78] = 0x02;
+    pci_conf[0x79] = 0x00;
+    pci_conf[0x80] = 0x00;
+    pci_conf[0x82] = 0x00;
     pci_conf[0xa0] = 0x08;
     pci_conf[0xa2] = 0x00;
     pci_conf[0xa3] = 0x00;
@@ -181,22 +296,37 @@ static void piix3_reset(PCIDevice *d)
     pci_conf[0xae] = 0x00;
 }
 
-int piix3_init(PCIBus *bus)
+static void piix_save(QEMUFile* f, void *opaque)
+{
+    PCIDevice *d = opaque;
+    pci_device_save(d, f);
+}
+
+static int piix_load(QEMUFile* f, void *opaque, int version_id)
+{
+    PCIDevice *d = opaque;
+    if (version_id != 2)
+        return -EINVAL;
+    return pci_device_load(d, f);
+}
+
+int piix_init(PCIBus *bus, int devfn)
 {
     PCIDevice *d;
     uint8_t *pci_conf;
 
-    d = pci_register_device(bus, "PIIX3", sizeof(PCIDevice),
-                                    -1, NULL, NULL);
-    register_savevm("PIIX3", 0, 1, generic_pci_save, generic_pci_load, d);
+    d = pci_register_device(bus, "PIIX", sizeof(PCIDevice),
+                                    devfn, NULL, NULL);
+    register_savevm("PIIX", 0, 2, piix_save, piix_load, d);
 
     piix3_dev = d;
     pci_conf = d->config;
 
     pci_conf[0x00] = 0x86; // Intel
     pci_conf[0x01] = 0x80;
-    pci_conf[0x02] = 0x00; // 82371SB PIIX3 PCI-to-ISA bridge (Step A1)
-    pci_conf[0x03] = 0x70;
+    pci_conf[0x02] = 0x2E; // 82371FB PIIX PCI-to-ISA bridge
+    pci_conf[0x03] = 0x12;
+    pci_conf[0x08] = 0x02; // Step A1
     pci_conf[0x0a] = 0x01; // class_sub = PCI_ISA
     pci_conf[0x0b] = 0x06; // class_base = PCI_bridge
     pci_conf[0x0e] = 0x80; // header_type = PCI_multifunction, generic
@@ -205,227 +335,50 @@ int piix3_init(PCIBus *bus)
     return d->devfn;
 }
 
-/***********************************************************/
-/* XXX: the following should be moved to the PC BIOS */
-
-static __attribute__((unused)) uint32_t isa_inb(uint32_t addr)
-{
-    return cpu_inb(NULL, addr);
-}
-
-static void isa_outb(uint32_t val, uint32_t addr)
+int piix3_init(PCIBus *bus, int devfn)
 {
-    cpu_outb(NULL, addr, val);
-}
-
-static __attribute__((unused)) uint32_t isa_inw(uint32_t addr)
-{
-    return cpu_inw(NULL, addr);
-}
-
-static __attribute__((unused)) void isa_outw(uint32_t val, uint32_t addr)
-{
-    cpu_outw(NULL, addr, val);
-}
-
-static __attribute__((unused)) uint32_t isa_inl(uint32_t addr)
-{
-    return cpu_inl(NULL, addr);
-}
-
-static __attribute__((unused)) void isa_outl(uint32_t val, uint32_t addr)
-{
-    cpu_outl(NULL, addr, val);
-}
-
-static uint32_t pci_bios_io_addr;
-static uint32_t pci_bios_mem_addr;
-/* host irqs corresponding to PCI irqs A-D */
-static uint8_t pci_irqs[4] = { 10, 11, 10, 11 };
-
-static void pci_config_writel(PCIDevice *d, uint32_t addr, uint32_t val)
-{
-    PCIBus *s = d->bus;
-    addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);
-    pci_data_write(s, addr, val, 4);
-}
-
-static void pci_config_writew(PCIDevice *d, uint32_t addr, uint32_t val)
-{
-    PCIBus *s = d->bus;
-    addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);
-    pci_data_write(s, addr, val, 2);
-}
+    PCIDevice *d;
+    uint8_t *pci_conf;
 
-static void pci_config_writeb(PCIDevice *d, uint32_t addr, uint32_t val)
-{
-    PCIBus *s = d->bus;
-    addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);
-    pci_data_write(s, addr, val, 1);
-}
+    d = pci_register_device(bus, "PIIX3", sizeof(PCIDevice),
+                                    devfn, NULL, NULL);
+    register_savevm("PIIX3", 0, 2, piix_save, piix_load, d);
 
-static __attribute__((unused)) uint32_t pci_config_readl(PCIDevice *d, uint32_t addr)
-{
-    PCIBus *s = d->bus;
-    addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);
-    return pci_data_read(s, addr, 4);
-}
+    piix3_dev = d;
+    pci_conf = d->config;
 
-static uint32_t pci_config_readw(PCIDevice *d, uint32_t addr)
-{
-    PCIBus *s = d->bus;
-    addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);
-    return pci_data_read(s, addr, 2);
-}
+    pci_conf[0x00] = 0x86; // Intel
+    pci_conf[0x01] = 0x80;
+    pci_conf[0x02] = 0x00; // 82371SB PIIX3 PCI-to-ISA bridge (Step A1)
+    pci_conf[0x03] = 0x70;
+    pci_conf[0x0a] = 0x01; // class_sub = PCI_ISA
+    pci_conf[0x0b] = 0x06; // class_base = PCI_bridge
+    pci_conf[0x0e] = 0x80; // header_type = PCI_multifunction, generic
 
-static uint32_t pci_config_readb(PCIDevice *d, uint32_t addr)
-{
-    PCIBus *s = d->bus;
-    addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);
-    return pci_data_read(s, addr, 1);
+    piix3_reset(d);
+    return d->devfn;
 }
 
-static void pci_set_io_region_addr(PCIDevice *d, int region_num, uint32_t addr)
+int piix4_init(PCIBus *bus, int devfn)
 {
-    PCIIORegion *r;
-    uint16_t cmd;
-    uint32_t ofs;
-
-    if ( region_num == PCI_ROM_SLOT ) {
-        ofs = 0x30;
-    }else{
-        ofs = 0x10 + region_num * 4;
-    }
-
-    pci_config_writel(d, ofs, addr);
-    r = &d->io_regions[region_num];
-
-    /* enable memory mappings */
-    cmd = pci_config_readw(d, PCI_COMMAND);
-    if ( region_num == PCI_ROM_SLOT )
-        cmd |= 2;
-    else if (r->type & PCI_ADDRESS_SPACE_IO)
-        cmd |= 1;
-    else
-        cmd |= 2;
-    pci_config_writew(d, PCI_COMMAND, cmd);
-}
+    PCIDevice *d;
+    uint8_t *pci_conf;
 
-static void pci_bios_init_device(PCIDevice *d)
-{
-    int class;
-    PCIIORegion *r;
-    uint32_t *paddr;
-    int i, pin, pic_irq, vendor_id, device_id;
-
-    class = pci_config_readw(d, PCI_CLASS_DEVICE);
-    vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
-    device_id = pci_config_readw(d, PCI_DEVICE_ID);
-    switch(class) {
-    case 0x0101:
-        if (vendor_id == 0x8086 && device_id == 0x7010) {
-            /* PIIX3 IDE */
-            pci_config_writew(d, 0x40, 0x8000); // enable IDE0
-            pci_config_writew(d, 0x42, 0x8000); // enable IDE1
-            goto default_map;
-        } else {
-            /* IDE: we map it as in ISA mode */
-            pci_set_io_region_addr(d, 0, 0x1f0);
-            pci_set_io_region_addr(d, 1, 0x3f4);
-            pci_set_io_region_addr(d, 2, 0x170);
-            pci_set_io_region_addr(d, 3, 0x374);
-        }
-        break;
-    case 0x0680:
-        if (vendor_id == 0x8086 && device_id == 0x7113) {
-            /*
-             * PIIX4 ACPI PM.
-             * Special device with special PCI config space. No ordinary BARs.
-             */
-            pci_config_writew(d, 0x20, 0x0000); // No smb bus IO enable
-            pci_config_writew(d, 0x22, 0x0000);
-            pci_config_writew(d, 0x3c, 0x0009); // Hardcoded IRQ9
-            pci_config_writew(d, 0x3d, 0x0001);
-        }
-        break;
-    case 0x0300:
-        if (vendor_id != 0x1234)
-            goto default_map;
-        /* VGA: map frame buffer to default Bochs VBE address */
-        pci_set_io_region_addr(d, 0, 0xE0000000);
-        break;
-    case 0x0800:
-        /* PIC */
-        vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
-        device_id = pci_config_readw(d, PCI_DEVICE_ID);
-        if (vendor_id == 0x1014) {
-            /* IBM */
-            if (device_id == 0x0046 || device_id == 0xFFFF) {
-                /* MPIC & MPIC2 */
-                pci_set_io_region_addr(d, 0, 0x80800000 + 0x00040000);
-            }
-        }
-        break;
-    case 0xff00:
-        if (vendor_id == 0x0106b &&
-            (device_id == 0x0017 || device_id == 0x0022)) {
-            /* macio bridge */
-            pci_set_io_region_addr(d, 0, 0x80800000);
-        }
-        break;
-    default:
-    default_map:
-        /* default memory mappings */
-        for(i = 0; i < PCI_NUM_REGIONS; i++) {
-            r = &d->io_regions[i];
-            if (r->size) {
-                if (r->type & PCI_ADDRESS_SPACE_IO)
-                    paddr = &pci_bios_io_addr;
-                else
-                    paddr = &pci_bios_mem_addr;
-                *paddr = (*paddr + r->size - 1) & ~(r->size - 1);
-                pci_set_io_region_addr(d, i, *paddr);
-                *paddr += r->size;
-            }
-        }
-        break;
-    }
+    d = pci_register_device(bus, "PIIX4", sizeof(PCIDevice),
+                                    devfn, NULL, NULL);
+    register_savevm("PIIX4", 0, 2, piix_save, piix_load, d);
 
-    /* map the interrupt */
-    pin = pci_config_readb(d, PCI_INTERRUPT_PIN);
-    if (pin != 0) {
-        pin = pci_slot_get_pirq(d, pin - 1);
-        pic_irq = pci_irqs[pin];
-        pci_config_writeb(d, PCI_INTERRUPT_LINE, pic_irq);
-    }
-}
+    piix4_dev = d;
+    pci_conf = d->config;
 
-/*
- * This function initializes the PCI devices as a normal PCI BIOS
- * would do. It is provided just in case the BIOS has no support for
- * PCI.
- */
-void pci_bios_init(void)
-{
-    int i, irq;
-    uint8_t elcr[2];
-
-    pci_bios_io_addr = 0xc000;
-    pci_bios_mem_addr = HVM_BELOW_4G_MMIO_START;
-
-    /* activate IRQ mappings */
-    elcr[0] = 0x00;
-    elcr[1] = 0x00;
-    for(i = 0; i < 4; i++) {
-        irq = pci_irqs[i];
-        /* set to trigger level */
-        elcr[irq >> 3] |= (1 << (irq & 7));
-        /* activate irq remapping in PIIX */
-        pci_config_writeb(piix3_dev, 0x60 + i, irq);
-    }
-    isa_outb(elcr[0], 0x4d0);
-    isa_outb(elcr[1], 0x4d1);
+    pci_conf[0x00] = 0x86; // Intel
+    pci_conf[0x01] = 0x80;
+    pci_conf[0x02] = 0x10; // 82371AB/EB/MB PIIX4 PCI-to-ISA bridge
+    pci_conf[0x03] = 0x71;
+    pci_conf[0x0a] = 0x01; // class_sub = PCI_ISA
+    pci_conf[0x0b] = 0x06; // class_base = PCI_bridge
+    pci_conf[0x0e] = 0x80; // header_type = PCI_multifunction, generic
 
-    pci_for_each_device(pci_bios_init_device);
+    piix4_reset(d);
+    return d->devfn;
 }
-
index 657f03bbe849cd7acc1c9637c4c39e45cd2604f8..fb7ab7b53d8d6aa87b4883eb3b734508f7d51ffe 100644 (file)
@@ -243,8 +243,8 @@ void pl011_init(uint32_t base, void *pic, int irq,
     s->cr = 0x300;
     s->flags = 0x90;
     if (chr){ 
-        qemu_chr_add_read_handler(chr, pl011_can_recieve, pl011_recieve, s);
-        qemu_chr_add_event_handler(chr, pl011_event);
+        qemu_chr_add_handlers(chr, pl011_can_recieve, pl011_recieve,
+                              pl011_event, s);
     }
     /* ??? Save/restore.  */
 }
index 49996ca91db8d6fa21dff57474e0a53a07d8ead5..549b3bfd1066ce673fcea05c8e9cc3795b630b8a 100644 (file)
@@ -1,5 +1,5 @@
 /* 
- * Arm PrimeCell PL080 DMA controller
+ * Arm PrimeCell PL080/PL081 DMA controller
  *
  * Copyright (c) 2006 CodeSourcery.
  * Written by Paul Brook
@@ -9,7 +9,7 @@
 
 #include "vl.h"
 
-#define PL080_NUM_CHANNELS 8
+#define PL080_MAX_CHANNELS 8
 #define PL080_CONF_E    0x1
 #define PL080_CONF_M1   0x2
 #define PL080_CONF_M2   0x4
@@ -45,7 +45,8 @@ typedef struct {
     uint32_t sync;
     uint32_t req_single;
     uint32_t req_burst;
-    pl080_channel chan[PL080_NUM_CHANNELS];
+    pl080_channel chan[PL080_MAX_CHANNELS];
+    int nchannels;
     /* Flag to avoid recursive DMA invocations.  */
     int running;
     void *pic;
@@ -55,6 +56,9 @@ typedef struct {
 static const unsigned char pl080_id[] =
 { 0x80, 0x10, 0x04, 0x0a, 0x0d, 0xf0, 0x05, 0xb1 };
 
+static const unsigned char pl081_id[] =
+{ 0x81, 0x10, 0x04, 0x0a, 0x0d, 0xf0, 0x05, 0xb1 };
+
 static void pl080_update(pl080_state *s)
 {
     if ((s->tc_int & s->tc_mask)
@@ -80,7 +84,7 @@ static void pl080_run(pl080_state *s)
     uint32_t req;
 
     s->tc_mask = 0;
-    for (c = 0; c < PL080_NUM_CHANNELS; c++) {
+    for (c = 0; c < s->nchannels; c++) {
         if (s->chan[c].conf & PL080_CCONF_ITC)
             s->tc_mask |= 1 << c;
         if (s->chan[c].conf & PL080_CCONF_IE)
@@ -99,7 +103,7 @@ cpu_abort(cpu_single_env, "DMA active\n");
     }
     s->running = 1;
     while (s->running) {
-        for (c = 0; c < PL080_NUM_CHANNELS; c++) {
+        for (c = 0; c < s->nchannels; c++) {
             ch = &s->chan[c];
 again:
             /* Test if thiws channel has any pending DMA requests.  */
@@ -185,10 +189,16 @@ static uint32_t pl080_read(void *opaque, target_phys_addr_t offset)
 
     offset -= s->base;
     if (offset >= 0xfe0 && offset < 0x1000) {
-        return pl080_id[(offset - 0xfe0) >> 2];
+        if (s->nchannels == 8) {
+            return pl080_id[(offset - 0xfe0) >> 2];
+        } else {
+            return pl081_id[(offset - 0xfe0) >> 2];
+        }
     }
     if (offset >= 0x100 && offset < 0x200) {
         i = (offset & 0xe0) >> 5;
+        if (i >= s->nchannels)
+            goto bad_offset;
         switch (offset >> 2) {
         case 0: /* SrcAddr */
             return s->chan[i].src;
@@ -217,7 +227,7 @@ static uint32_t pl080_read(void *opaque, target_phys_addr_t offset)
         return s->err_int;
     case 7: /* EnbldChns */
         mask = 0;
-        for (i = 0; i < PL080_NUM_CHANNELS; i++) {
+        for (i = 0; i < s->nchannels; i++) {
             if (s->chan[i].conf & PL080_CCONF_E)
                 mask |= 1 << i;
         }
@@ -248,6 +258,8 @@ static void pl080_write(void *opaque, target_phys_addr_t offset,
     offset -= s->base;
     if (offset >= 0x100 && offset < 0x200) {
         i = (offset & 0xe0) >> 5;
+        if (i >= s->nchannels)
+            goto bad_offset;
         switch (offset >> 2) {
         case 0: /* SrcAddr */
             s->chan[i].src = value;
@@ -293,6 +305,7 @@ static void pl080_write(void *opaque, target_phys_addr_t offset,
         s->sync = value;
         break;
     default:
+    bad_offset:
         cpu_abort(cpu_single_env, "pl080_write: Bad offset %x\n", offset);
     }
     pl080_update(s);
@@ -310,7 +323,9 @@ static CPUWriteMemoryFunc *pl080_writefn[] = {
    pl080_write
 };
 
-void *pl080_init(uint32_t base, void *pic, int irq)
+/* The PL080 and PL081 are the same except for the number of channels
+   they implement (8 and 2 respectively).  */
+void *pl080_init(uint32_t base, void *pic, int irq, int nchannels)
 {
     int iomemtype;
     pl080_state *s;
@@ -322,6 +337,7 @@ void *pl080_init(uint32_t base, void *pic, int irq)
     s->base = base;
     s->pic = pic;
     s->irq = irq;
+    s->nchannels = nchannels;
     /* ??? Save/restore.  */
     return s;
 }
index ecebe35eb3ee383ab734942588ff489a129a3e35..16de16c0dd7e78f3f6f5202bcecd46f6d1123a05 100644 (file)
@@ -185,10 +185,11 @@ static void pl110_update_display(void *opaque)
     addr = base;
 
     dirty = cpu_physical_memory_get_dirty(addr, VGA_DIRTY_FLAG);
+    new_dirty = dirty;
     for (i = 0; i < s->rows; i++) {
-        new_dirty = 0;
-        if ((addr & TARGET_PAGE_MASK) + src_width >= TARGET_PAGE_SIZE) {
+        if ((addr & ~TARGET_PAGE_MASK) + src_width >= TARGET_PAGE_SIZE) {
             uint32_t tmp;
+            new_dirty = 0;
             for (tmp = 0; tmp < src_width; tmp += TARGET_PAGE_SIZE) {
                 new_dirty |= cpu_physical_memory_get_dirty(addr + tmp,
                                                            VGA_DIRTY_FLAG);
index db05035b01727a51dd0446f4d6214db11f7a6d3e..ed533aca1905100b82fe6ed9f0a123ec0d0dff61 100644 (file)
@@ -79,7 +79,7 @@ static drawfn glue(pl110_draw_fn_,BITS)[18] =
 #endif
 
 #define FN_2(x, y) FN(x, y) FN(x+1, y)
-#define FN_4(x, y) FN_2(x, y) FN_2(x+1, y)
+#define FN_4(x, y) FN_2(x, y) FN_2(x+2, y)
 #define FN_8(y) FN_4(0, y) FN_4(4, y)
 
 static void glue(pl110_draw_line1_,NAME)(uint32_t *pallette, uint8_t *d, const uint8_t *src, int width)
index 3743ad78615bad6474ad4f6d15d0c05ac189f216..b0865c1646fb144fcdc4b259941417ec60cccd71 100644 (file)
@@ -201,64 +201,6 @@ void cpu_ppc_reset (CPUState *env)
 }
 #endif
 
-static void PPC_io_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
-{
-    cpu_outb(NULL, addr & 0xffff, value);
-}
-
-static uint32_t PPC_io_readb (void *opaque, target_phys_addr_t addr)
-{
-    uint32_t ret = cpu_inb(NULL, addr & 0xffff);
-    return ret;
-}
-
-static void PPC_io_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
-{
-#ifdef TARGET_WORDS_BIGENDIAN
-    value = bswap16(value);
-#endif
-    cpu_outw(NULL, addr & 0xffff, value);
-}
-
-static uint32_t PPC_io_readw (void *opaque, target_phys_addr_t addr)
-{
-    uint32_t ret = cpu_inw(NULL, addr & 0xffff);
-#ifdef TARGET_WORDS_BIGENDIAN
-    ret = bswap16(ret);
-#endif
-    return ret;
-}
-
-static void PPC_io_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
-{
-#ifdef TARGET_WORDS_BIGENDIAN
-    value = bswap32(value);
-#endif
-    cpu_outl(NULL, addr & 0xffff, value);
-}
-
-static uint32_t PPC_io_readl (void *opaque, target_phys_addr_t addr)
-{
-    uint32_t ret = cpu_inl(NULL, addr & 0xffff);
-
-#ifdef TARGET_WORDS_BIGENDIAN
-    ret = bswap32(ret);
-#endif
-    return ret;
-}
-
-CPUWriteMemoryFunc *PPC_io_write[] = {
-    &PPC_io_writeb,
-    &PPC_io_writew,
-    &PPC_io_writel,
-};
-
-CPUReadMemoryFunc *PPC_io_read[] = {
-    &PPC_io_readb,
-    &PPC_io_readw,
-    &PPC_io_readl,
-};
-
 /*****************************************************************************/
 /* Debug port */
 void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val)
index 42d599588e6f7f53829590ca587bcdd9e0431bdd..1e0fd2e9da73f5ef2e31a61b6df73cbdd95f0fa8 100644 (file)
@@ -305,7 +305,7 @@ static void ppc_chrp_init(int ram_size, int vga_ram_size, int boot_device,
     SetIRQFunc *set_irq;
     void *pic;
     m48t59_t *nvram;
-    int PPC_io_memory, unin_memory;
+    int unin_memory;
     int linux_boot, i;
     unsigned long bios_offset, vga_bios_offset;
     uint32_t kernel_base, kernel_size, initrd_base, initrd_size;
@@ -417,16 +417,15 @@ static void ppc_chrp_init(int ram_size, int vga_ram_size, int boot_device,
         isa_mem_base = 0x80000000;
         
         /* Register 2 MB of ISA IO space */
-        PPC_io_memory = cpu_register_io_memory(0, PPC_io_read, PPC_io_write, NULL);
-        cpu_register_physical_memory(0xfe000000, 0x00200000, PPC_io_memory);
-        
+        isa_mmio_init(0xfe000000, 0x00200000);
+
         /* init basic PC hardware */
         pic = heathrow_pic_init(&heathrow_pic_mem_index);
         set_irq = heathrow_pic_set_irq;
         pci_bus = pci_grackle_init(0xfec00000, pic);
-        vga_initialize(pci_bus, ds, phys_ram_base + ram_size, 
-                       ram_size, vga_ram_size,
-                       vga_bios_offset, vga_bios_size);
+        pci_vga_init(pci_bus, ds, phys_ram_base + ram_size, 
+                     ram_size, vga_ram_size,
+                     vga_bios_offset, vga_bios_size);
 
         /* XXX: suppress that */
         isa_pic = pic_init(pic_irq_request, NULL);
@@ -437,7 +436,7 @@ static void ppc_chrp_init(int ram_size, int vga_ram_size, int boot_device,
         for(i = 0; i < nb_nics; i++) {
             if (!nd_table[i].model)
                 nd_table[i].model = "ne2k_pci";
-            pci_nic_init(pci_bus, &nd_table[i]);
+            pci_nic_init(pci_bus, &nd_table[i], -1);
         }
         
         pci_cmd646_ide_init(pci_bus, &bs_table[0], 0);
@@ -463,8 +462,7 @@ static void ppc_chrp_init(int ram_size, int vga_ram_size, int boot_device,
         isa_mem_base = 0x80000000;
         
         /* Register 8 MB of ISA IO space */
-        PPC_io_memory = cpu_register_io_memory(0, PPC_io_read, PPC_io_write, NULL);
-        cpu_register_physical_memory(0xF2000000, 0x00800000, PPC_io_memory);
+        isa_mmio_init(0xf2000000, 0x00800000);
         
         /* UniN init */
         unin_memory = cpu_register_io_memory(0, unin_read, unin_write, NULL);
@@ -474,9 +472,9 @@ static void ppc_chrp_init(int ram_size, int vga_ram_size, int boot_device,
         set_irq = openpic_set_irq;
         pci_bus = pci_pmac_init(pic);
         /* init basic PC hardware */
-        vga_initialize(pci_bus, ds, phys_ram_base + ram_size,
-                       ram_size, vga_ram_size,
-                       vga_bios_offset, vga_bios_size);
+        pci_vga_init(pci_bus, ds, phys_ram_base + ram_size,
+                     ram_size, vga_ram_size,
+                     vga_bios_offset, vga_bios_size);
 
         /* XXX: suppress that */
         isa_pic = pic_init(pic_irq_request, NULL);
@@ -485,7 +483,7 @@ static void ppc_chrp_init(int ram_size, int vga_ram_size, int boot_device,
         serial_init(&pic_set_irq_new, isa_pic, 0x3f8, 4, serial_hds[0]);
         
         for(i = 0; i < nb_nics; i++) {
-            pci_ne2000_init(pci_bus, &nd_table[i]);
+            pci_ne2000_init(pci_bus, &nd_table[i], -1);
         }
         
 #if 1
index a4d7ddfe7e0fa275cc42917e59e7235631871ccc..c4b7ff5baa3af127d1b1b3b87b1146cc1da682c6 100644 (file)
@@ -525,7 +525,6 @@ static void ppc_prep_init(int ram_size, int vga_ram_size, int boot_device,
 {
     CPUState *env;
     char buf[1024];
-    SetIRQFunc *set_irq;
     m48t59_t *nvram;
     int PPC_io_memory;
     int linux_boot, i, nb_nics1, bios_size;
@@ -612,8 +611,8 @@ static void ppc_prep_init(int ram_size, int vga_ram_size, int boot_device,
     cpu_register_physical_memory(0x80000000, 0x00800000, PPC_io_memory);
 
     /* init basic PC hardware */
-    vga_initialize(pci_bus, ds, phys_ram_base + ram_size, ram_size, 
-                   vga_ram_size, 0, 0);
+    pci_vga_init(pci_bus, ds, phys_ram_base + ram_size, ram_size, 
+                 vga_ram_size, 0, 0);
     rtc_init(0x70, 8);
     //    openpic = openpic_init(0x00000000, 0xF0000000, 1);
     isa_pic = pic_init(pic_irq_request, first_cpu);
index a31b74c80a7cccb63c01a3cae03e4025b8c7db76..3d93c065ff3dd2a3d0bfa2fd365db7b4857f2322 100644 (file)
@@ -117,11 +117,15 @@ static CPUReadMemoryFunc *PPC_PCIIO_read[] = {
     &PPC_PCIIO_readl,
 };
 
-static void prep_set_irq(PCIDevice *d, void *pic, int irq_num, int level)
+/* Don't know if this matches real hardware, but it agrees with OHW.  */
+static int prep_map_irq(PCIDevice *pci_dev, int irq_num)
 {
-    /* XXX: we do not simulate the hardware - we rely on the BIOS to
-       set correctly for irq line field */
-    pic_set_irq(d->config[PCI_INTERRUPT_LINE], level);
+    return (irq_num + (pci_dev->devfn >> 3)) & 1;
+}
+
+static void prep_set_irq(void *pic, int irq_num, int level)
+{
+    pic_set_irq(irq_num ? 11 : 9, level);
 }
 
 PCIBus *pci_prep_init(void)
@@ -131,7 +135,7 @@ PCIBus *pci_prep_init(void)
     int PPC_io_memory;
 
     s = qemu_mallocz(sizeof(PREPPCIState));
-    s->bus = pci_register_bus(prep_set_irq, NULL, 0);
+    s->bus = pci_register_bus(prep_set_irq, prep_map_irq, NULL, 0, 2);
 
     register_ioport_write(0xcf8, 4, 4, pci_prep_addr_writel, s);
     register_ioport_read(0xcf8, 4, 4, pci_prep_addr_readl, s);
index 8438a5e853b5a47c07100c5b71a0c1b209ef5ef5..3794c603662b2f49c9c9e723ff671b3d6d137030 100644 (file)
@@ -560,7 +560,7 @@ void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
     s->common.update_arg = update_arg;
     ps2_reset(&s->common);
     register_savevm("ps2mouse", 0, 2, ps2_mouse_save, ps2_mouse_load, s);
-    qemu_add_mouse_event_handler(ps2_mouse_event, s, 0);
+    qemu_add_mouse_event_handler(ps2_mouse_event, s, 0, "QEMU PS/2 Mouse");
     qemu_register_reset(ps2_reset, &s->common);
     return s;
 }
diff --git a/tools/ioemu/hw/realview.c b/tools/ioemu/hw/realview.c
new file mode 100644 (file)
index 0000000..ea42705
--- /dev/null
@@ -0,0 +1,138 @@
+/* 
+ * ARM RealView Baseboard System emulation.
+ *
+ * Copyright (c) 2006 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licenced under the GPL.
+ */
+
+#include "vl.h"
+#include "arm_pic.h"
+
+/* Board init.  */
+
+static void realview_init(int ram_size, int vga_ram_size, int boot_device,
+                     DisplayState *ds, const char **fd_filename, int snapshot,
+                     const char *kernel_filename, const char *kernel_cmdline,
+                     const char *initrd_filename)
+{
+    CPUState *env;
+    void *pic;
+    void *scsi_hba;
+    PCIBus *pci_bus;
+    NICInfo *nd;
+    int n;
+    int done_smc = 0;
+
+    env = cpu_init();
+    cpu_arm_set_model(env, ARM_CPUID_ARM926);
+    //cpu_arm_set_model(env, ARM_CPUID_ARM11MPCORE);
+    /* ??? RAM shoud repeat to fill physical memory space.  */
+    /* SDRAM at address zero.  */
+    cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
+
+    arm_sysctl_init(0x10000000, 0xc1400400);
+    pic = arm_pic_init_cpu(env);
+    /* ??? The documentation says GIC1 is nFIQ and either GIC2 or GIC3
+       is nIRQ (there are inconsistencies).  However Linux 2.6.17 expects
+       GIC1 to be nIRQ and ignores all the others, so do that for now.  */
+    pic = arm_gic_init(0x10040000, pic, ARM_PIC_CPU_IRQ);
+    pl050_init(0x10006000, pic, 20, 0);
+    pl050_init(0x10007000, pic, 21, 1);
+
+    pl011_init(0x10009000, pic, 12, serial_hds[0]);
+    pl011_init(0x1000a000, pic, 13, serial_hds[1]);
+    pl011_init(0x1000b000, pic, 14, serial_hds[2]);
+    pl011_init(0x1000c000, pic, 15, serial_hds[3]);
+
+    /* DMA controller is optional, apparently.  */
+    pl080_init(0x10030000, pic, 24, 2);
+
+    sp804_init(0x10011000, pic, 4);
+    sp804_init(0x10012000, pic, 5);
+
+    pl110_init(ds, 0x10020000, pic, 23, 1);
+
+    pci_bus = pci_vpb_init(pic, 48, 1);
+    if (usb_enabled) {
+        usb_ohci_init(pci_bus, 3, -1);
+    }
+    scsi_hba = lsi_scsi_init(pci_bus, -1);
+    for (n = 0; n < MAX_DISKS; n++) {
+        if (bs_table[n]) {
+            lsi_scsi_attach(scsi_hba, bs_table[n], n);
+        }
+    }
+    for(n = 0; n < nb_nics; n++) {
+        nd = &nd_table[n];
+        if (!nd->model)
+            nd->model = done_smc ? "rtl8139" : "smc91c111";
+        if (strcmp(nd->model, "smc91c111") == 0) {
+            smc91c111_init(nd, 0x4e000000, pic, 28);
+        } else {
+            pci_nic_init(pci_bus, nd, -1);
+        }
+    }
+
+    /* Memory map for RealView Emulation Baseboard:  */
+    /* 0x10000000 System registers.  */
+    /*  0x10001000 System controller.  */
+    /*  0x10002000 Two-Wire Serial Bus.  */
+    /* 0x10003000 Reserved.  */
+    /*  0x10004000 AACI.  */
+    /*  0x10005000 MCI.  */
+    /* 0x10006000 KMI0.  */
+    /* 0x10007000 KMI1.  */
+    /*  0x10008000 Character LCD.  */
+    /* 0x10009000 UART0.  */
+    /* 0x1000a000 UART1.  */
+    /* 0x1000b000 UART2.  */
+    /* 0x1000c000 UART3.  */
+    /*  0x1000d000 SSPI.  */
+    /*  0x1000e000 SCI.  */
+    /* 0x1000f000 Reserved.  */
+    /*  0x10010000 Watchdog.  */
+    /* 0x10011000 Timer 0+1.  */
+    /* 0x10012000 Timer 2+3.  */
+    /*  0x10013000 GPIO 0.  */
+    /*  0x10014000 GPIO 1.  */
+    /*  0x10015000 GPIO 2.  */
+    /* 0x10016000 Reserved.  */
+    /*  0x10017000 RTC.  */
+    /*  0x10018000 DMC.  */
+    /*  0x10019000 PCI controller config.  */
+    /*  0x10020000 CLCD.  */
+    /* 0x10030000 DMA Controller.  */
+    /* 0x10040000 GIC1 (FIQ1).  */
+    /* 0x10050000 GIC2 (IRQ1).  */
+    /*  0x10060000 GIC3 (FIQ2).  */
+    /*  0x10070000 GIC4 (IRQ2).  */
+    /*  0x10080000 SMC.  */
+    /*  0x40000000 NOR flash.  */
+    /*  0x44000000 DoC flash.  */
+    /*  0x48000000 SRAM.  */
+    /*  0x4c000000 Configuration flash.  */
+    /* 0x4e000000 Ethernet.  */
+    /*  0x4f000000 USB.  */
+    /*  0x50000000 PISMO.  */
+    /*  0x54000000 PISMO.  */
+    /*  0x58000000 PISMO.  */
+    /*  0x5c000000 PISMO.  */
+    /* 0x60000000 PCI.  */
+    /* 0x61000000 PCI Self Config.  */
+    /* 0x62000000 PCI Config.  */
+    /* 0x63000000 PCI IO.  */
+    /* 0x64000000 PCI mem 0.  */
+    /* 0x68000000 PCI mem 1.  */
+    /* 0x6c000000 PCI mem 2.  */
+
+    arm_load_kernel(env, ram_size, kernel_filename, kernel_cmdline,
+                    initrd_filename, 0x33b);
+}
+
+QEMUMachine realview_machine = {
+    "realview",
+    "ARM RealView Emulation Baseboard (ARM926EJ-S)",
+    realview_init
+};
index 3c67507ff4459aa66a998558e4a4592fa7936781..6883803fe30a9f00bf70159e67276cd1814150e5 100644 (file)
@@ -3122,6 +3122,8 @@ static void rtl8139_save(QEMUFile* f,void* opaque)
     RTL8139State* s=(RTL8139State*)opaque;
     int i;
 
+    pci_device_save(s->pci_dev, f);
+
     qemu_put_buffer(f, s->phys, 6);
     qemu_put_buffer(f, s->mult, 8);
 
@@ -3203,12 +3205,18 @@ static void rtl8139_save(QEMUFile* f,void* opaque)
 static int rtl8139_load(QEMUFile* f,void* opaque,int version_id)
 {
     RTL8139State* s=(RTL8139State*)opaque;
-    int i;
+    int i, ret;
 
     /* just 2 versions for now */
-    if (version_id > 2)
+    if (version_id > 3)
             return -EINVAL;
 
+    if (version_id >= 3) {
+        ret = pci_device_load(s->pci_dev, f);
+        if (ret < 0)
+            return ret;
+    }
+
     /* saved since version 1 */
     qemu_get_buffer(f, s->phys, 6);
     qemu_get_buffer(f, s->mult, 8);
@@ -3401,7 +3409,7 @@ static void rtl8139_timer(void *opaque)
 }
 #endif /* RTL8139_ONBOARD_TIMER */
 
-void pci_rtl8139_init(PCIBus *bus, NICInfo *nd)
+void pci_rtl8139_init(PCIBus *bus, NICInfo *nd, int devfn)
 {
     PCIRTL8139State *d;
     RTL8139State *s;
@@ -3410,7 +3418,7 @@ void pci_rtl8139_init(PCIBus *bus, NICInfo *nd)
     
     d = (PCIRTL8139State *)pci_register_device(bus,
                                               "RTL8139", sizeof(PCIRTL8139State),
-                                              -1
+                                              devfn
                                               NULL, NULL);
     pci_conf = d->dev.config;
     pci_conf[0x00] = 0xec; /* Realtek 8139 */
@@ -3462,9 +3470,7 @@ void pci_rtl8139_init(PCIBus *bus, NICInfo *nd)
     s->cplus_txbuffer_offset = 0;
              
     instance = pci_bus_num(bus) << 8 | s->pci_dev->devfn;
-    register_savevm("rtl8139", instance, 2, rtl8139_save, rtl8139_load, s);
-    register_savevm("rtl8139_pci", instance, 1, generic_pci_save, 
-                    generic_pci_load, &d->dev);
+    register_savevm("rtl8139", instance, 3, rtl8139_save, rtl8139_load, s);
 
 #if RTL8139_ONBOARD_TIMER
     s->timer = qemu_new_timer(vm_clock, rtl8139_timer, s);
index decab1f42b919c91bcad08fe9141f469287ab829..c6280fd5599c4103b33978a3af8fdd594345d3ac 100644 (file)
@@ -7,6 +7,10 @@
  * Written by Paul Brook
  *
  * This code is licenced under the LGPL.
+ *
+ * Note that this file only handles the SCSI architecture model and device
+ * commands.  Emultion of interface/link layer protocols is handled by
+ * the host adapter emulation.
  */
 
 //#define DEBUG_SCSI
@@ -24,150 +28,245 @@ do { fprintf(stderr, "scsi-disk: " fmt , ##args); } while (0)
 #include "vl.h"
 
 #define SENSE_NO_SENSE        0
+#define SENSE_NOT_READY       2
+#define SENSE_HARDWARE_ERROR  4
 #define SENSE_ILLEGAL_REQUEST 5
 
-struct SCSIDevice
-{
-    int command;
+#define SCSI_DMA_BUF_SIZE    65536
+
+typedef struct SCSIRequest {
+    SCSIDevice *dev;
     uint32_t tag;
-    BlockDriverState *bdrv;
-    /* The qemu block layer uses a fixed 512 byte sector size.
-       This is the number of 512 byte blocks in a single scsi sector.  */
-    int cluster_size;
-    /* When transfering data buf_pos and buf_len contain a partially
-       transferred block of data (or response to a command), and
-       sector/sector_count identify any remaining sectors.
-       Both sector and sector_count are in terms of qemu 512 byte blocks.  */
     /* ??? We should probably keep track of whether the data trasfer is
        a read or a write.  Currently we rely on the host getting it right.  */
+    /* Both sector and sector_count are in terms of qemu 512 byte blocks.  */
     int sector;
     int sector_count;
-    int buf_pos;
+    /* The amounnt of data in the buffer.  */
     int buf_len;
+    uint8_t dma_buf[SCSI_DMA_BUF_SIZE];
+    BlockDriverAIOCB *aiocb;
+    struct SCSIRequest *next;
+} SCSIRequest;
+
+struct SCSIDevice
+{
+    BlockDriverState *bdrv;
+    SCSIRequest *requests;
+    /* The qemu block layer uses a fixed 512 byte sector size.
+       This is the number of 512 byte blocks in a single scsi sector.  */
+    int cluster_size;
     int sense;
-    char buf[512];
+    int tcq;
+    /* Completion functions may be called from either scsi_{read,write}_data
+       or from the AIO completion routines.  */
     scsi_completionfn completion;
     void *opaque;
 };
 
-static void scsi_command_complete(SCSIDevice *s, int sense)
+/* Global pool of SCSIRequest structures.  */
+static SCSIRequest *free_requests = NULL;
+
+static SCSIRequest *scsi_new_request(SCSIDevice *s, uint32_t tag)
 {
-    s->sense = sense;
-    s->completion(s->opaque, s->tag, sense);
+    SCSIRequest *r;
+
+    if (free_requests) {
+        r = free_requests;
+        free_requests = r->next;
+    } else {
+        r = qemu_malloc(sizeof(SCSIRequest));
+    }
+    r->dev = s;
+    r->tag = tag;
+    r->sector_count = 0;
+    r->buf_len = 0;
+    r->aiocb = NULL;
+
+    r->next = s->requests;
+    s->requests = r;
+    return r;
 }
 
-/* Read data from a scsi device.  Returns nonzero on failure.  */
-int scsi_read_data(SCSIDevice *s, uint8_t *data, uint32_t len)
+static void scsi_remove_request(SCSIRequest *r)
 {
-    uint32_t n;
-
-    DPRINTF("Read %d (%d/%d)\n", len, s->buf_len, s->sector_count);
-    if (s->buf_len == 0 && s->sector_count == 0)
-        return 1;
+    SCSIRequest *last;
+    SCSIDevice *s = r->dev;
 
-    if (s->buf_len) {
-        n = s->buf_len;
-        if (n > len)
-            n = len;
-        memcpy(data, s->buf + s->buf_pos, n);
-        s->buf_pos += n;
-        s->buf_len -= n;
-        data += n;
-        len -= n;
-        if (s->buf_len == 0)
-            s->buf_pos = 0;
+    if (s->requests == r) {
+        s->requests = r->next;
+    } else {
+        last = s->requests;
+        while (last && last->next != r)
+            last = last->next;
+        if (last) {
+            last->next = r->next;
+        } else {
+            BADF("Orphaned request\n");
+        }
     }
+    r->next = free_requests;
+    free_requests = r;
+}
+
+static SCSIRequest *scsi_find_request(SCSIDevice *s, uint32_t tag)
+{
+    SCSIRequest *r;
 
-    n = len / 512;
-    if (n > s->sector_count)
-      n = s->sector_count;
+    r = s->requests;
+    while (r && r->tag != tag)
+        r = r->next;
 
-    if (n != 0) {
-        bdrv_read(s->bdrv, s->sector, data, n);
-        data += n * 512;
-        len -= n * 512;
-        s->sector += n;
-        s->sector_count -= n;
-    }
+    return r;
+}
 
-    if (len && s->sector_count) {
-        bdrv_read(s->bdrv, s->sector, s->buf, 1);
-        s->sector++;
-        s->sector_count--;
-        s->buf_pos = 0;
-        s->buf_len = 512;
-        /* Recurse to complete the partial read.  */
-        return scsi_read_data(s, data, len);
+/* Helper function for command completion.  */
+static void scsi_command_complete(SCSIRequest *r, int sense)
+{
+    SCSIDevice *s = r->dev;
+    uint32_t tag;
+    DPRINTF("Command complete tag=0x%x sense=%d\n", r->tag, sense);
+    s->sense = sense;
+    tag = r->tag;
+    scsi_remove_request(r);
+    s->completion(s->opaque, SCSI_REASON_DONE, tag, sense);
+}
+
+/* Cancel a pending data transfer.  */
+void scsi_cancel_io(SCSIDevice *s, uint32_t tag)
+{
+    SCSIRequest *r;
+    DPRINTF("Cancel tag=0x%x\n", tag);
+    r = scsi_find_request(s, tag);
+    if (r) {
+        if (r->aiocb)
+            bdrv_aio_cancel(r->aiocb);
+        r->aiocb = NULL;
+        scsi_remove_request(r);
     }
+}
 
-    if (len != 0)
-        return 1;
+static void scsi_read_complete(void * opaque, int ret)
+{
+    SCSIRequest *r = (SCSIRequest *)opaque;
+    SCSIDevice *s = r->dev;
 
-    if (s->buf_len == 0 && s->sector_count == 0)
-        scsi_command_complete(s, SENSE_NO_SENSE);
+    if (ret) {
+        DPRINTF("IO error\n");
+        scsi_command_complete(r, SENSE_HARDWARE_ERROR);
+        return;
+    }
+    DPRINTF("Data ready tag=0x%x len=%d\n", r->tag, r->buf_len);
 
-    return 0;
+    s->completion(s->opaque, SCSI_REASON_DATA, r->tag, r->buf_len);
 }
 
-/* Read data to a scsi device.  Returns nonzero on failure.  */
-int scsi_write_data(SCSIDevice *s, uint8_t *data, uint32_t len)
+/* Read more data from scsi device into buffer.  */
+void scsi_read_data(SCSIDevice *s, uint32_t tag)
 {
+    SCSIRequest *r;
     uint32_t n;
 
-    DPRINTF("Write %d (%d/%d)\n", len, s->buf_len, s->sector_count);
-    if (s->buf_pos != 0) {
-        BADF("Bad state on write\n");
-        return 1;
+    r = scsi_find_request(s, tag);
+    if (!r) {
+        BADF("Bad read tag 0x%x\n", tag);
+        /* ??? This is the wrong error.  */
+        scsi_command_complete(r, SENSE_HARDWARE_ERROR);
+        return;
+    }
+    if (r->sector_count == (uint32_t)-1) {
+        DPRINTF("Read buf_len=%d\n", r->buf_len);
+        r->sector_count = 0;
+        s->completion(s->opaque, SCSI_REASON_DATA, r->tag, r->buf_len);
+        return;
+    }
+    DPRINTF("Read sector_count=%d\n", r->sector_count);
+    if (r->sector_count == 0) {
+        scsi_command_complete(r, SENSE_NO_SENSE);
+        return;
     }
 
-    if (s->sector_count == 0)
-        return 1;
+    n = r->sector_count;
+    if (n > SCSI_DMA_BUF_SIZE / 512)
+        n = SCSI_DMA_BUF_SIZE / 512;
+
+    r->buf_len = n * 512;
+    r->aiocb = bdrv_aio_read(s->bdrv, r->sector, r->dma_buf, n,
+                             scsi_read_complete, r);
+    if (r->aiocb == NULL)
+        scsi_command_complete(r, SENSE_HARDWARE_ERROR);
+    r->sector += n;
+    r->sector_count -= n;
+}
 
-    if (s->buf_len != 0 || len < 512) {
-        n = 512 - s->buf_len;
-        if (n > len)
-            n = len;
-
-        memcpy(s->buf + s->buf_len, data, n);
-        data += n;
-        s->buf_len += n;
-        len -= n;
-        if (s->buf_len == 512) {
-            /* A full sector has been accumulated. Write it to disk.  */
-            bdrv_write(s->bdrv, s->sector, s->buf, 1);
-            s->buf_len = 0;
-            s->sector++;
-            s->sector_count--;
-        }
-    }
+static void scsi_write_complete(void * opaque, int ret)
+{
+    SCSIRequest *r = (SCSIRequest *)opaque;
+    SCSIDevice *s = r->dev;
+    uint32_t len;
 
-    n = len / 512;
-    if (n > s->sector_count)
-        n = s->sector_count;
+    if (ret) {
+        fprintf(stderr, "scsi-disc: IO write error\n");
+        exit(1);
+    }
 
-    if (n != 0) {
-        bdrv_write(s->bdrv, s->sector, data, n);
-        data += n * 512;
-        len -= n * 512;
-        s->sector += n;
-        s->sector_count -= n;
+    r->aiocb = NULL;
+    if (r->sector_count == 0) {
+        scsi_command_complete(r, SENSE_NO_SENSE);
+    } else {
+        len = r->sector_count * 512;
+        if (len > SCSI_DMA_BUF_SIZE) {
+            len = SCSI_DMA_BUF_SIZE;
+        }
+        r->buf_len = len;
+        DPRINTF("Write complete tag=0x%x more=%d\n", r->tag, len);
+        s->completion(s->opaque, SCSI_REASON_DATA, r->tag, len);
     }
+}
 
-    if (len >= 512)
-        return 1;
+/* Write data to a scsi device.  Returns nonzero on failure.
+   The transfer may complete asynchronously.  */
+int scsi_write_data(SCSIDevice *s, uint32_t tag)
+{
+    SCSIRequest *r;
+    uint32_t n;
 
-    if (len && s->sector_count) {
-        /* Recurse to complete the partial write.  */
-        return scsi_write_data(s, data, len);
+    DPRINTF("Write data tag=0x%x\n", tag);
+    r = scsi_find_request(s, tag);
+    if (!r) {
+        BADF("Bad write tag 0x%x\n", tag);
+        scsi_command_complete(r, SENSE_HARDWARE_ERROR);
+        return 1;
+    }
+    if (r->aiocb)
+        BADF("Data transfer already in progress\n");
+    n = r->buf_len / 512;
+    if (n) {
+        r->aiocb = bdrv_aio_write(s->bdrv, r->sector, r->dma_buf, n,
+                                  scsi_write_complete, r);
+        if (r->aiocb == NULL)
+            scsi_command_complete(r, SENSE_HARDWARE_ERROR);
+        r->sector += n;
+        r->sector_count -= n;
+    } else {
+        /* Invoke completion routine to fetch data from host.  */
+        scsi_write_complete(r, 0);
     }
 
-    if (len != 0)
-        return 1;
+    return 0;
+}
 
-    if (s->sector_count == 0)
-        scsi_command_complete(s, SENSE_NO_SENSE);
+/* Return a pointer to the data buffer.  */
+uint8_t *scsi_get_buf(SCSIDevice *s, uint32_t tag)
+{
+    SCSIRequest *r;
 
-    return 0;
+    r = scsi_find_request(s, tag);
+    if (!r) {
+        BADF("Bad buffer tag 0x%x\n", tag);
+        return NULL;
+    }
+    return r->dma_buf;
 }
 
 /* Execute a scsi command.  Returns the length of the data expected by the
@@ -182,15 +281,23 @@ int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf, int lun)
     uint32_t len;
     int cmdlen;
     int is_write;
-
-    s->command = buf[0];
-    s->tag = tag;
-    s->sector_count = 0;
-    s->buf_pos = 0;
-    s->buf_len = 0;
+    uint8_t command;
+    uint8_t *outbuf;
+    SCSIRequest *r;
+
+    command = buf[0];
+    r = scsi_find_request(s, tag);
+    if (r) {
+        BADF("Tag 0x%x already in use\n", tag);
+        scsi_cancel_io(s, tag);
+    }
+    /* ??? Tags are not unique for different luns.  We only implement a
+       single lun, so this should not matter.  */
+    r = scsi_new_request(s, tag);
+    outbuf = r->dma_buf;
     is_write = 0;
-    DPRINTF("Command: 0x%02x", buf[0]);
-    switch (s->command >> 5) {
+    DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", lun, tag, buf[0]);
+    switch (command >> 5) {
     case 0:
         lba = buf[3] | (buf[2] << 8) | ((buf[1] & 0x1f) << 16);
         len = buf[4];
@@ -213,7 +320,7 @@ int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf, int lun)
         cmdlen = 12;
         break;
     default:
-        BADF("Unsupported command length, command %x\n", s->command);
+        BADF("Unsupported command length, command %x\n", command);
         goto fail;
     }
 #ifdef DEBUG_SCSI
@@ -230,7 +337,7 @@ int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf, int lun)
         DPRINTF("Unimplemented LUN %d\n", lun ? lun : buf[1] >> 5);
         goto fail;
     }
-    switch (s->command) {
+    switch (command) {
     case 0x0:
        DPRINTF("Test Unit Ready\n");
        break;
@@ -239,33 +346,35 @@ int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf, int lun)
         if (len < 4)
             goto fail;
         memset(buf, 0, 4);
-        s->buf[0] = 0xf0;
-        s->buf[1] = 0;
-        s->buf[2] = s->sense;
-        s->buf_len = 4;
+        outbuf[0] = 0xf0;
+        outbuf[1] = 0;
+        outbuf[2] = s->sense;
+        r->buf_len = 4;
         break;
     case 0x12:
         DPRINTF("Inquiry (len %d)\n", len);
         if (len < 36) {
             BADF("Inquiry buffer too small (%d)\n", len);
         }
-       memset(s->buf, 0, 36);
+       memset(outbuf, 0, 36);
        if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
-           s->buf[0] = 5;
-            s->buf[1] = 0x80;
-           memcpy(&s->buf[16], "QEMU CD-ROM    ", 16);
+           outbuf[0] = 5;
+            outbuf[1] = 0x80;
+           memcpy(&outbuf[16], "QEMU CD-ROM    ", 16);
        } else {
-           s->buf[0] = 0;
-           memcpy(&s->buf[16], "QEMU HARDDISK  ", 16);
+           outbuf[0] = 0;
+           memcpy(&outbuf[16], "QEMU HARDDISK  ", 16);
        }
-       memcpy(&s->buf[8], "QEMU   ", 8);
-        memcpy(&s->buf[32], QEMU_VERSION, 4);
+       memcpy(&outbuf[8], "QEMU   ", 8);
+        memcpy(&outbuf[32], QEMU_VERSION, 4);
         /* Identify device as SCSI-3 rev 1.
            Some later commands are also implemented. */
-       s->buf[2] = 3;
-       s->buf[3] = 2; /* Format 2 */
-       s->buf[4] = 32;
-       s->buf_len = 36;
+       outbuf[2] = 3;
+       outbuf[3] = 2; /* Format 2 */
+       outbuf[4] = 32;
+        /* Sync data transfer and TCQ.  */
+        outbuf[7] = 0x10 | (s->tcq ? 0x02 : 0);
+       r->buf_len = 36;
        break;
     case 0x16:
         DPRINTF("Reserve(6)\n");
@@ -280,17 +389,17 @@ int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf, int lun)
     case 0x1a:
     case 0x5a:
         {
-            char *p;
+            uint8_t *p;
             int page;
 
             page = buf[2] & 0x3f;
             DPRINTF("Mode Sense (page %d, len %d)\n", page, len);
-            p = s->buf;
+            p = outbuf;
             memset(p, 0, 4);
-            s->buf[1] = 0; /* Default media type.  */
-            s->buf[3] = 0; /* Block descriptor length.  */
+            outbuf[1] = 0; /* Default media type.  */
+            outbuf[3] = 0; /* Block descriptor length.  */
             if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
-                s->buf[2] = 0x80; /* Readonly.  */
+                outbuf[2] = 0x80; /* Readonly.  */
             }
             p += 4;
             if ((page == 8 || page == 0x3f)) {
@@ -330,10 +439,10 @@ int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf, int lun)
                 p[21] = (16 * 176) & 0xff;
                 p += 21;
             }
-            s->buf_len = p - s->buf;
-            s->buf[0] = s->buf_len - 4;
-            if (s->buf_len > len)
-                s->buf_len = len;
+            r->buf_len = p - outbuf;
+            outbuf[0] = r->buf_len - 4;
+            if (r->buf_len > len)
+                r->buf_len = len;
         }
         break;
     case 0x1b:
@@ -346,29 +455,36 @@ int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf, int lun)
     case 0x25:
        DPRINTF("Read Capacity\n");
         /* The normal LEN field for this command is zero.  */
-       memset(s->buf, 0, 8);
+       memset(outbuf, 0, 8);
        bdrv_get_geometry(s->bdrv, &nb_sectors);
-       s->buf[0] = (nb_sectors >> 24) & 0xff;
-       s->buf[1] = (nb_sectors >> 16) & 0xff;
-       s->buf[2] = (nb_sectors >> 8) & 0xff;
-       s->buf[3] = nb_sectors & 0xff;
-       s->buf[4] = 0;
-       s->buf[5] = 0;
-        s->buf[6] = s->cluster_size * 2;
-       s->buf[7] = 0;
-       s->buf_len = 8;
+        /* Returned value is the address of the last sector.  */
+        if (nb_sectors) {
+            nb_sectors--;
+            outbuf[0] = (nb_sectors >> 24) & 0xff;
+            outbuf[1] = (nb_sectors >> 16) & 0xff;
+            outbuf[2] = (nb_sectors >> 8) & 0xff;
+            outbuf[3] = nb_sectors & 0xff;
+            outbuf[4] = 0;
+            outbuf[5] = 0;
+            outbuf[6] = s->cluster_size * 2;
+            outbuf[7] = 0;
+            r->buf_len = 8;
+        } else {
+            scsi_command_complete(r, SENSE_NOT_READY);
+            return 0;
+        }
        break;
     case 0x08:
     case 0x28:
         DPRINTF("Read (sector %d, count %d)\n", lba, len);
-        s->sector = lba * s->cluster_size;
-        s->sector_count = len * s->cluster_size;
+        r->sector = lba * s->cluster_size;
+        r->sector_count = len * s->cluster_size;
         break;
     case 0x0a:
     case 0x2a:
         DPRINTF("Write (sector %d, count %d)\n", lba, len);
-        s->sector = lba * s->cluster_size;
-        s->sector_count = len * s->cluster_size;
+        r->sector = lba * s->cluster_size;
+        r->sector_count = len * s->cluster_size;
         is_write = 1;
         break;
     case 0x35:
@@ -386,18 +502,18 @@ int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf, int lun)
             DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);
             switch(format) {
             case 0:
-                toclen = cdrom_read_toc(nb_sectors, s->buf, msf, start_track);
+                toclen = cdrom_read_toc(nb_sectors, outbuf, msf, start_track);
                 break;
             case 1:
                 /* multi session : only a single session defined */
                 toclen = 12;
-                memset(s->buf, 0, 12);
-                s->buf[1] = 0x0a;
-                s->buf[2] = 0x01;
-                s->buf[3] = 0x01;
+                memset(outbuf, 0, 12);
+                outbuf[1] = 0x0a;
+                outbuf[2] = 0x01;
+                outbuf[3] = 0x01;
                 break;
             case 2:
-                toclen = cdrom_read_toc_raw(nb_sectors, s->buf, msf, start_track);
+                toclen = cdrom_read_toc_raw(nb_sectors, outbuf, msf, start_track);
                 break;
             default:
                 goto error_cmd;
@@ -405,7 +521,7 @@ int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf, int lun)
             if (toclen > 0) {
                 if (len > toclen)
                   len = toclen;
-                s->buf_len = len;
+                r->buf_len = len;
                 break;
             }
         error_cmd:
@@ -414,11 +530,11 @@ int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf, int lun)
         }
     case 0x46:
         DPRINTF("Get Configuration (rt %d, maxlen %d)\n", buf[1] & 3, len);
-        memset(s->buf, 0, 8);
+        memset(outbuf, 0, 8);
         /* ??? This shoud probably return much more information.  For now
            just return the basic header indicating the CD-ROM profile.  */
-        s->buf[7] = 8; // CD-ROM
-        s->buf_len = 8;
+        outbuf[7] = 8; // CD-ROM
+        r->buf_len = 8;
         break;
     case 0x56:
         DPRINTF("Reserve(10)\n");
@@ -434,30 +550,36 @@ int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf, int lun)
         DPRINTF("Report LUNs (len %d)\n", len);
         if (len < 16)
             goto fail;
-        memset(s->buf, 0, 16);
-        s->buf[3] = 8;
-        s->buf_len = 16;
+        memset(outbuf, 0, 16);
+        outbuf[3] = 8;
+        r->buf_len = 16;
         break;
     default:
        DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
     fail:
-        scsi_command_complete(s, SENSE_ILLEGAL_REQUEST);
+        scsi_command_complete(r, SENSE_ILLEGAL_REQUEST);
        return 0;
     }
-    if (s->sector_count == 0 && s->buf_len == 0) {
-        scsi_command_complete(s, SENSE_NO_SENSE);
+    if (r->sector_count == 0 && r->buf_len == 0) {
+        scsi_command_complete(r, SENSE_NO_SENSE);
+    }
+    len = r->sector_count * 512 + r->buf_len;
+    if (is_write) {
+        return -len;
+    } else {
+        if (!r->sector_count)
+            r->sector_count = -1;
+        return len;
     }
-    len = s->sector_count * 512 + s->buf_len;
-    return is_write ? -len : len;
 }
 
 void scsi_disk_destroy(SCSIDevice *s)
 {
-    bdrv_close(s->bdrv);
     qemu_free(s);
 }
 
 SCSIDevice *scsi_disk_init(BlockDriverState *bdrv,
+                           int tcq,
                            scsi_completionfn completion,
                            void *opaque)
 {
@@ -465,6 +587,7 @@ SCSIDevice *scsi_disk_init(BlockDriverState *bdrv,
 
     s = (SCSIDevice *)qemu_mallocz(sizeof(SCSIDevice));
     s->bdrv = bdrv;
+    s->tcq = tcq;
     s->completion = completion;
     s->opaque = opaque;
     if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
index b99e774eae3f790b0acb27f62abe244980733dec..56ff301d698fc74eed2cd211afe6c92bf4929f57 100644 (file)
@@ -79,7 +79,7 @@
 #define WRITE_MAX_TOTAL_RETRIES 10
 
 struct SerialState {
-    uint8_t divider;
+    uint16_t divider;
     uint8_t rbr; /* receive register */
     uint8_t ier;
     uint8_t iir; /* read only */
@@ -420,7 +420,7 @@ static void serial_save(QEMUFile *f, void *opaque)
 {
     SerialState *s = opaque;
 
-    qemu_put_8s(f,&s->divider);
+    qemu_put_be16s(f,&s->divider);
     qemu_put_8s(f,&s->rbr);
     qemu_put_8s(f,&s->ier);
     qemu_put_8s(f,&s->iir);
@@ -435,10 +435,13 @@ static int serial_load(QEMUFile *f, void *opaque, int version_id)
 {
     SerialState *s = opaque;
 
-    if(version_id != 1)
+    if(version_id > 2)
         return -EINVAL;
 
-    qemu_get_8s(f,&s->divider);
+    if (version_id >= 2)
+        qemu_get_be16s(f, &s->divider);
+    else
+        s->divider = qemu_get_byte(f);
     qemu_get_8s(f,&s->rbr);
     qemu_get_8s(f,&s->ier);
     qemu_get_8s(f,&s->iir);
@@ -468,13 +471,13 @@ SerialState *serial_init(SetIRQFunc *set_irq, void *opaque,
     s->msr = UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS;
     s->write_retry_timer = qemu_new_timer(vm_clock, serial_chr_write, s);
 
-    register_savevm("serial", base, 1, serial_save, serial_load, s);
+    register_savevm("serial", base, 2, serial_save, serial_load, s);
 
     register_ioport_write(base, 8, 1, serial_ioport_write, s);
     register_ioport_read(base, 8, 1, serial_ioport_read, s);
     s->chr = chr;
-    qemu_chr_add_read_handler(chr, serial_can_receive1, serial_receive1, s);
-    qemu_chr_add_event_handler(chr, serial_event);
+    qemu_chr_add_handlers(chr, serial_can_receive1, serial_receive1,
+                          serial_event, s);
     return s;
 }
 
@@ -556,13 +559,13 @@ SerialState *serial_mm_init (SetIRQFunc *set_irq, void *opaque,
     s->it_shift = it_shift;
     s->write_retry_timer = qemu_new_timer(vm_clock, serial_chr_write, s);
 
-    register_savevm("serial", base, 1, serial_save, serial_load, s);
+    register_savevm("serial", base, 2, serial_save, serial_load, s);
 
     s_io_memory = cpu_register_io_memory(0, serial_mm_read,
                                          serial_mm_write, s);
     cpu_register_physical_memory(base, 8 << it_shift, s_io_memory);
     s->chr = chr;
-    qemu_chr_add_read_handler(chr, serial_can_receive1, serial_receive1, s);
-    qemu_chr_add_event_handler(chr, serial_event);
+    qemu_chr_add_handlers(chr, serial_can_receive1, serial_receive1,
+                          serial_event, s);
     return s;
 }
index 21f9bc0aeed0d23d86e5b8c97d79e8e942d51ee0..164ce716236e720a1bde599535a6e2c4bdc373a8 100644 (file)
@@ -299,9 +299,8 @@ static void init_serial1(SH7750State * s, int serial_nb)
     }
 
     s->serial1 = chr;
-    qemu_chr_add_read_handler(chr, serial1_can_receive,
-                             serial1_receive, s);
-    qemu_chr_add_event_handler(chr, serial1_event);
+    qemu_chr_add_handlers(chr, serial1_can_receive,
+                         serial1_receive, serial1_event, s);
 }
 
 /**********************************************************************
@@ -415,9 +414,8 @@ static void init_serial2(SH7750State * s, int serial_nb)
     }
 
     s->serial2 = chr;
-    qemu_chr_add_read_handler(chr, serial2_can_receive,
-                             serial2_receive, s);
-    qemu_chr_add_event_handler(chr, serial2_event);
+    qemu_chr_add_handlers(chr, serial2_can_receive,
+                         serial2_receive, serial1_event, s);
 }
 
 static void init_serial_ports(SH7750State * s)
index 904f44e515c0593c7c4d595f7fc98051da40f8b2..a48a7af5c01ee80af083dfae9cb1014cd92bfc2b 100644 (file)
@@ -123,10 +123,7 @@ static void slavio_misc_mem_writeb(void *opaque, target_phys_addr_t addr, uint32
        break;
     case 0xa000000:
        MISC_DPRINTF("Write power management %2.2x\n", val & 0xff);
-#if 0
-        // XXX almost works
         cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HALT);
-#endif
        break;
     }
 }
index b13e7c46f9a2a00648c20bc26d34497b503057fb..e72bb70e05b00faa1334905e62ca5b094d46ffd8 100644 (file)
  *
  */
 
+/*
+ * Modifications:
+ *  2006-Aug-10  Igor Kovalenko :   Renamed KBDQueue to SERIOQueue, implemented
+ *                                  serial mouse queue.
+ *                                  Implemented serial mouse protocol.
+ */
+
 #ifdef DEBUG_SERIAL
 #define SER_DPRINTF(fmt, args...) \
 do { printf("SER: " fmt , ##args); } while (0)
@@ -58,7 +65,7 @@ do { printf("KBD: " fmt , ##args); } while (0)
 #endif
 #ifdef DEBUG_MOUSE
 #define MS_DPRINTF(fmt, args...) \
-do { printf("SER: " fmt , ##args); } while (0)
+do { printf("MSC: " fmt , ##args); } while (0)
 #else
 #define MS_DPRINTF(fmt, args...)
 #endif
@@ -67,26 +74,28 @@ typedef enum {
     chn_a, chn_b,
 } chn_id_t;
 
+#define CHN_C(s) ((s)->chn == chn_b? 'b' : 'a')
+
 typedef enum {
     ser, kbd, mouse,
 } chn_type_t;
 
-#define KBD_QUEUE_SIZE 256
+#define SERIO_QUEUE_SIZE 256
 
 typedef struct {
-    uint8_t data[KBD_QUEUE_SIZE];
+    uint8_t data[SERIO_QUEUE_SIZE];
     int rptr, wptr, count;
-} KBDQueue;
+} SERIOQueue;
 
 typedef struct ChannelState {
     int irq;
     int reg;
-    int rxint, txint;
+    int rxint, txint, rxint_under_svc, txint_under_svc;
     chn_id_t chn; // this channel, A (base+4) or B (base+0)
     chn_type_t type;
     struct ChannelState *otherchn;
     uint8_t rx, tx, wregs[16], rregs[16];
-    KBDQueue queue;
+    SERIOQueue queue;
     CharDriverState *chr;
 } ChannelState;
 
@@ -99,17 +108,18 @@ struct SerialState {
 static void handle_kbd_command(ChannelState *s, int val);
 static int serial_can_receive(void *opaque);
 static void serial_receive_byte(ChannelState *s, int ch);
+static inline void set_txint(ChannelState *s);
 
 static void put_queue(void *opaque, int b)
 {
     ChannelState *s = opaque;
-    KBDQueue *q = &s->queue;
+    SERIOQueue *q = &s->queue;
 
-    KBD_DPRINTF("put: 0x%02x\n", b);
-    if (q->count >= KBD_QUEUE_SIZE)
+    SER_DPRINTF("channel %c put: 0x%02x\n", CHN_C(s), b);
+    if (q->count >= SERIO_QUEUE_SIZE)
         return;
     q->data[q->wptr] = b;
-    if (++q->wptr == KBD_QUEUE_SIZE)
+    if (++q->wptr == SERIO_QUEUE_SIZE)
         q->wptr = 0;
     q->count++;
     serial_receive_byte(s, 0);
@@ -118,34 +128,43 @@ static void put_queue(void *opaque, int b)
 static uint32_t get_queue(void *opaque)
 {
     ChannelState *s = opaque;
-    KBDQueue *q = &s->queue;
+    SERIOQueue *q = &s->queue;
     int val;
     
     if (q->count == 0) {
        return 0;
     } else {
         val = q->data[q->rptr];
-        if (++q->rptr == KBD_QUEUE_SIZE)
+        if (++q->rptr == SERIO_QUEUE_SIZE)
             q->rptr = 0;
         q->count--;
     }
-    KBD_DPRINTF("get 0x%02x\n", val);
+    KBD_DPRINTF("channel %c get 0x%02x\n", CHN_C(s), val);
     if (q->count > 0)
        serial_receive_byte(s, 0);
     return val;
 }
 
-static void slavio_serial_update_irq(ChannelState *s)
+static int slavio_serial_update_irq_chn(ChannelState *s)
 {
     if ((s->wregs[1] & 1) && // interrupts enabled
        (((s->wregs[1] & 2) && s->txint == 1) || // tx ints enabled, pending
         ((((s->wregs[1] & 0x18) == 8) || ((s->wregs[1] & 0x18) == 0x10)) &&
          s->rxint == 1) || // rx ints enabled, pending
         ((s->wregs[15] & 0x80) && (s->rregs[0] & 0x80)))) { // break int e&p
-        pic_set_irq(s->irq, 1);
-    } else {
-        pic_set_irq(s->irq, 0);
+        return 1;
     }
+    return 0;
+}
+
+static void slavio_serial_update_irq(ChannelState *s)
+{
+    int irq;
+
+    irq = slavio_serial_update_irq_chn(s);
+    irq |= slavio_serial_update_irq_chn(s->otherchn);
+
+    pic_set_irq(s->irq, irq);
 }
 
 static void slavio_serial_reset_chn(ChannelState *s)
@@ -167,6 +186,7 @@ static void slavio_serial_reset_chn(ChannelState *s)
 
     s->rx = s->tx = 0;
     s->rxint = s->txint = 0;
+    s->rxint_under_svc = s->txint_under_svc = 0;
 }
 
 static void slavio_serial_reset(void *opaque)
@@ -179,45 +199,118 @@ static void slavio_serial_reset(void *opaque)
 static inline void clr_rxint(ChannelState *s)
 {
     s->rxint = 0;
-    if (s->chn == 0)
+    s->rxint_under_svc = 0;
+    if (s->chn == chn_a)
         s->rregs[3] &= ~0x20;
-    else {
+    else
         s->otherchn->rregs[3] &= ~4;
-    }
+    if (s->txint)
+        set_txint(s);
+    else
+        s->rregs[2] = 6;
     slavio_serial_update_irq(s);
 }
 
 static inline void set_rxint(ChannelState *s)
 {
     s->rxint = 1;
-    if (s->chn == 0)
-        s->rregs[3] |= 0x20;
-    else {
-        s->otherchn->rregs[3] |= 4;
+    if (!s->txint_under_svc) {
+        s->rxint_under_svc = 1;
+        if (s->chn == chn_a)
+            s->rregs[3] |= 0x20;
+        else
+            s->otherchn->rregs[3] |= 4;
+        s->rregs[2] = 4;
+        slavio_serial_update_irq(s);
     }
-    slavio_serial_update_irq(s);
 }
 
 static inline void clr_txint(ChannelState *s)
 {
     s->txint = 0;
-    if (s->chn == 0)
+    s->txint_under_svc = 0;
+    if (s->chn == chn_a)
         s->rregs[3] &= ~0x10;
-    else {
+    else
         s->otherchn->rregs[3] &= ~2;
-    }
+    if (s->rxint)
+        set_rxint(s);
+    else
+        s->rregs[2] = 6;
     slavio_serial_update_irq(s);
 }
 
 static inline void set_txint(ChannelState *s)
 {
     s->txint = 1;
-    if (s->chn == 0)
-        s->rregs[3] |= 0x10;
-    else {
-        s->otherchn->rregs[3] |= 2;
+    if (!s->rxint_under_svc) {
+        s->txint_under_svc = 1;
+        if (s->chn == chn_a)
+            s->rregs[3] |= 0x10;
+        else
+            s->otherchn->rregs[3] |= 2;
+        s->rregs[2] = 0;
+        slavio_serial_update_irq(s);
     }
-    slavio_serial_update_irq(s);
+}
+
+static void slavio_serial_update_parameters(ChannelState *s)
+{
+    int speed, parity, data_bits, stop_bits;
+    QEMUSerialSetParams ssp;
+
+    if (!s->chr || s->type != ser)
+        return;
+
+    if (s->wregs[4] & 1) {
+        if (s->wregs[4] & 2)
+            parity = 'E';
+        else
+            parity = 'O';
+    } else {
+        parity = 'N';
+    }
+    if ((s->wregs[4] & 0x0c) == 0x0c)
+        stop_bits = 2;
+    else
+        stop_bits = 1;
+    switch (s->wregs[5] & 0x60) {
+    case 0x00:
+        data_bits = 5;
+        break;
+    case 0x20:
+        data_bits = 7;
+        break;
+    case 0x40:
+        data_bits = 6;
+        break;
+    default:
+    case 0x60:
+        data_bits = 8;
+        break;
+    }
+    speed = 2457600 / ((s->wregs[12] | (s->wregs[13] << 8)) + 2);
+    switch (s->wregs[4] & 0xc0) {
+    case 0x00:
+        break;
+    case 0x40:
+        speed /= 16;
+        break;
+    case 0x80:
+        speed /= 32;
+        break;
+    default:
+    case 0xc0:
+        speed /= 64;
+        break;
+    }
+    ssp.speed = speed;
+    ssp.parity = parity;
+    ssp.data_bits = data_bits;
+    ssp.stop_bits = stop_bits;
+    SER_DPRINTF("channel %c: speed=%d parity=%c data=%d stop=%d\n", CHN_C(s),
+                speed, parity, data_bits, stop_bits);
+    qemu_chr_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
 }
 
 static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
@@ -233,7 +326,7 @@ static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint
     s = &ser->chn[channel];
     switch (saddr) {
     case 0:
-       SER_DPRINTF("Write channel %c, reg[%d] = %2.2x\n", channel? 'b' : 'a', s->reg, val & 0xff);
+       SER_DPRINTF("Write channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg, val & 0xff);
        newreg = 0;
        switch (s->reg) {
        case 0:
@@ -243,23 +336,31 @@ static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint
            case 8:
                newreg |= 0x8;
                break;
-           case 0x20:
-                clr_rxint(s);
-               break;
            case 0x28:
                 clr_txint(s);
                break;
            case 0x38:
-                clr_rxint(s);
-                clr_txint(s);
+                if (s->rxint_under_svc)
+                    clr_rxint(s);
+                else if (s->txint_under_svc)
+                    clr_txint(s);
                break;
            default:
                break;
            }
            break;
-       case 1 ... 8:
-       case 10 ... 15:
+        case 1 ... 3:
+        case 6 ... 8:
+        case 10 ... 11:
+        case 14 ... 15:
+           s->wregs[s->reg] = val;
+           break;
+        case 4:
+        case 5:
+        case 12:
+        case 13:
            s->wregs[s->reg] = val;
+            slavio_serial_update_parameters(s);
            break;
        case 9:
            switch (val & 0xc0) {
@@ -286,7 +387,7 @@ static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint
            s->reg = 0;
        break;
     case 1:
-       SER_DPRINTF("Write channel %c, ch %d\n", channel? 'b' : 'a', val);
+       SER_DPRINTF("Write channel %c, ch %d\n", CHN_C(s), val);
        if (s->wregs[5] & 8) { // tx enabled
            s->tx = val;
            if (s->chr)
@@ -294,11 +395,9 @@ static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint
            else if (s->type == kbd) {
                handle_kbd_command(s, val);
            }
-           s->txint = 1;
            s->rregs[0] |= 4; // Tx buffer empty
            s->rregs[1] |= 1; // All sent
             set_txint(s);
-           slavio_serial_update_irq(s);
        }
        break;
     default:
@@ -319,18 +418,18 @@ static uint32_t slavio_serial_mem_readb(void *opaque, target_phys_addr_t addr)
     s = &ser->chn[channel];
     switch (saddr) {
     case 0:
-       SER_DPRINTF("Read channel %c, reg[%d] = %2.2x\n", channel? 'b' : 'a', s->reg, s->rregs[s->reg]);
+       SER_DPRINTF("Read channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg, s->rregs[s->reg]);
        ret = s->rregs[s->reg];
        s->reg = 0;
        return ret;
     case 1:
        s->rregs[0] &= ~1;
         clr_rxint(s);
-       if (s->type == kbd)
+       if (s->type == kbd || s->type == mouse)
            ret = get_queue(s);
        else
            ret = s->rx;
-       SER_DPRINTF("Read channel %c, ch %d\n", channel? 'b' : 'a', ret);
+       SER_DPRINTF("Read channel %c, ch %d\n", CHN_C(s), ret);
        return ret;
     default:
        break;
@@ -341,16 +440,20 @@ static uint32_t slavio_serial_mem_readb(void *opaque, target_phys_addr_t addr)
 static int serial_can_receive(void *opaque)
 {
     ChannelState *s = opaque;
+    int ret;
+
     if (((s->wregs[3] & 1) == 0) // Rx not enabled
        || ((s->rregs[0] & 1) == 1)) // char already available
-       return 0;
+       ret = 0;
     else
-       return 1;
+       ret = 1;
+    //SER_DPRINTF("channel %c can receive %d\n", CHN_C(s), ret);
+    return ret;
 }
 
 static void serial_receive_byte(ChannelState *s, int ch)
 {
-    SER_DPRINTF("put ch %d\n", ch);
+    SER_DPRINTF("channel %c put ch %d\n", CHN_C(s), ch);
     s->rregs[0] |= 1;
     s->rx = ch;
     set_rxint(s);
@@ -393,6 +496,8 @@ static void slavio_serial_save_chn(QEMUFile *f, ChannelState *s)
     qemu_put_be32s(f, &s->reg);
     qemu_put_be32s(f, &s->rxint);
     qemu_put_be32s(f, &s->txint);
+    qemu_put_be32s(f, &s->rxint_under_svc);
+    qemu_put_be32s(f, &s->txint_under_svc);
     qemu_put_8s(f, &s->rx);
     qemu_put_8s(f, &s->tx);
     qemu_put_buffer(f, s->wregs, 16);
@@ -409,13 +514,17 @@ static void slavio_serial_save(QEMUFile *f, void *opaque)
 
 static int slavio_serial_load_chn(QEMUFile *f, ChannelState *s, int version_id)
 {
-    if (version_id != 1)
+    if (version_id > 2)
         return -EINVAL;
 
     qemu_get_be32s(f, &s->irq);
     qemu_get_be32s(f, &s->reg);
     qemu_get_be32s(f, &s->rxint);
     qemu_get_be32s(f, &s->txint);
+    if (version_id >= 2) {
+        qemu_get_be32s(f, &s->rxint_under_svc);
+        qemu_get_be32s(f, &s->txint_under_svc);
+    }
     qemu_get_8s(f, &s->rx);
     qemu_get_8s(f, &s->tx);
     qemu_get_buffer(f, s->wregs, 16);
@@ -456,13 +565,13 @@ SerialState *slavio_serial_init(int base, int irq, CharDriverState *chr1, CharDr
        s->chn[i].chn = 1 - i;
        s->chn[i].type = ser;
        if (s->chn[i].chr) {
-           qemu_chr_add_read_handler(s->chn[i].chr, serial_can_receive, serial_receive1, &s->chn[i]);
-           qemu_chr_add_event_handler(s->chn[i].chr, serial_event);
+           qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive,
+                                  serial_receive1, serial_event, &s->chn[i]);
        }
     }
     s->chn[0].otherchn = &s->chn[1];
     s->chn[1].otherchn = &s->chn[0];
-    register_savevm("slavio_serial", base, 1, slavio_serial_save, slavio_serial_load, s);
+    register_savevm("slavio_serial", base, 2, slavio_serial_save, slavio_serial_load, s);
     qemu_register_reset(slavio_serial_reset, s);
     slavio_serial_reset(s);
     return s;
@@ -512,9 +621,44 @@ static void sunmouse_event(void *opaque,
     ChannelState *s = opaque;
     int ch;
 
-    // XXX
-    ch = 0x42;
-    serial_receive_byte(s, ch);
+    /* XXX: SDL sometimes generates nul events: we delete them */
+    if (dx == 0 && dy == 0 && dz == 0 && buttons_state == 0)
+        return;
+    MS_DPRINTF("dx=%d dy=%d buttons=%01x\n", dx, dy, buttons_state);
+
+    ch = 0x80 | 0x7; /* protocol start byte, no buttons pressed */
+
+    if (buttons_state & MOUSE_EVENT_LBUTTON)
+        ch ^= 0x4;
+    if (buttons_state & MOUSE_EVENT_MBUTTON)
+        ch ^= 0x2;
+    if (buttons_state & MOUSE_EVENT_RBUTTON)
+        ch ^= 0x1;
+
+    put_queue(s, ch);
+
+    ch = dx;
+
+    if (ch > 127)
+        ch=127;
+    else if (ch < -127)
+        ch=-127;
+
+    put_queue(s, ch & 0xff);
+
+    ch = -dy;
+
+    if (ch > 127)
+        ch=127;
+    else if (ch < -127)
+        ch=-127;
+
+    put_queue(s, ch & 0xff);
+
+    // MSC protocol specify two extra motion bytes
+
+    put_queue(s, 0);
+    put_queue(s, 0);
 }
 
 void slavio_serial_ms_kbd_init(int base, int irq)
@@ -538,7 +682,7 @@ void slavio_serial_ms_kbd_init(int base, int irq)
     slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read, slavio_serial_mem_write, s);
     cpu_register_physical_memory(base, SERIAL_MAXADDR, slavio_serial_io_memory);
 
-    qemu_add_mouse_event_handler(sunmouse_event, &s->chn[0], 0);
+    qemu_add_mouse_event_handler(sunmouse_event, &s->chn[0], 0, "QEMU Sun Mouse");
     qemu_add_kbd_event_handler(sunkbd_event, &s->chn[1]);
     qemu_register_reset(slavio_serial_reset, s);
     slavio_serial_reset(s);
diff --git a/tools/ioemu/hw/smbus.h b/tools/ioemu/hw/smbus.h
new file mode 100644 (file)
index 0000000..76fc3c8
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * QEMU SMBus API
+ * 
+ * Copyright (c) 2007 Arastra, Inc.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+typedef struct SMBusDevice SMBusDevice;
+
+struct SMBusDevice {
+    uint8_t addr;
+    void (*quick_cmd)(SMBusDevice *dev, uint8_t read);
+    void (*send_byte)(SMBusDevice *dev, uint8_t val);
+    uint8_t (*receive_byte)(SMBusDevice *dev);
+    void (*write_byte)(SMBusDevice *dev, uint8_t cmd, uint8_t val);
+    uint8_t (*read_byte)(SMBusDevice *dev, uint8_t cmd);
+    void (*write_word)(SMBusDevice *dev, uint8_t cmd, uint16_t val);
+    uint16_t (*read_word)(SMBusDevice *dev, uint8_t cmd);
+    void (*write_block)(SMBusDevice *dev, uint8_t cmd, uint8_t len, uint8_t *buf);
+    uint8_t (*read_block)(SMBusDevice *dev, uint8_t cmd, uint8_t *buf);
+};
diff --git a/tools/ioemu/hw/smbus_eeprom.c b/tools/ioemu/hw/smbus_eeprom.c
new file mode 100644 (file)
index 0000000..d401b17
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * QEMU SMBus EEPROM device
+ * 
+ * Copyright (c) 2007 Arastra, Inc.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "vl.h"
+
+//#define DEBUG
+
+typedef struct SMBusEEPROMDevice {
+    SMBusDevice dev;
+    uint8_t *data;
+    uint8_t offset;
+} SMBusEEPROMDevice;
+
+static void eeprom_quick_cmd(SMBusDevice *dev, uint8_t read)
+{
+#ifdef DEBUG
+    printf("eeprom_quick_cmd: addr=0x%02x read=%d\n", dev->addr, read);
+#endif
+}
+
+static void eeprom_send_byte(SMBusDevice *dev, uint8_t val)
+{
+    SMBusEEPROMDevice *eeprom = (SMBusEEPROMDevice *) dev;
+#ifdef DEBUG
+    printf("eeprom_send_byte: addr=0x%02x val=0x%02x\n", dev->addr, val);
+#endif
+    eeprom->offset = val;
+}
+
+static uint8_t eeprom_receive_byte(SMBusDevice *dev)
+{
+    SMBusEEPROMDevice *eeprom = (SMBusEEPROMDevice *) dev;
+    uint8_t val = eeprom->data[eeprom->offset++];
+#ifdef DEBUG
+    printf("eeprom_receive_byte: addr=0x%02x val=0x%02x\n", dev->addr, val);
+#endif
+    return val;
+}
+
+static void eeprom_write_byte(SMBusDevice *dev, uint8_t cmd, uint8_t val)
+{
+    SMBusEEPROMDevice *eeprom = (SMBusEEPROMDevice *) dev;
+#ifdef DEBUG
+    printf("eeprom_write_byte: addr=0x%02x cmd=0x%02x val=0x%02x\n", dev->addr,
+           cmd, val);
+#endif
+    eeprom->data[cmd] = val;
+}
+
+static uint8_t eeprom_read_byte(SMBusDevice *dev, uint8_t cmd)
+{
+    SMBusEEPROMDevice *eeprom = (SMBusEEPROMDevice *) dev;
+    uint8_t val = eeprom->data[cmd];
+#ifdef DEBUG
+    printf("eeprom_read_byte: addr=0x%02x cmd=0x%02x val=0x%02x\n", dev->addr,
+           cmd, val);
+#endif
+    return val;
+}
+
+SMBusDevice *smbus_eeprom_device_init(uint8_t addr, uint8_t *buf)
+{
+    SMBusEEPROMDevice *eeprom = qemu_mallocz(sizeof(SMBusEEPROMDevice));
+    eeprom->dev.addr = addr;
+    eeprom->dev.quick_cmd = eeprom_quick_cmd;
+    eeprom->dev.send_byte = eeprom_send_byte;
+    eeprom->dev.receive_byte = eeprom_receive_byte;
+    eeprom->dev.write_byte = eeprom_write_byte;
+    eeprom->dev.read_byte = eeprom_read_byte;
+    eeprom->data = buf;
+    eeprom->offset = 0;
+    return (SMBusDevice *) eeprom;
+}
index 214e92efc0fd2782c22a57fb6ded021ad078075d..0249cfe98b2953d842b57181ad594093e9ae274d 100644 (file)
@@ -159,7 +159,6 @@ static void smc91c111_do_tx(smc91c111_state *s)
     int len;
     int control;
     int add_crc;
-    uint32_t crc;
     int packetnum;
     uint8_t *p;
 
@@ -192,6 +191,8 @@ static void smc91c111_do_tx(smc91c111_state *s)
            about.  */
         add_crc = (control & 0x10) || (s->tcr & TCR_NOCRC) == 0;
         if (add_crc) {
+            uint32_t crc;
+
             crc = crc32(~0, p, len);
             memcpy(p + len, &crc, 4);
             len += 4;
@@ -615,7 +616,7 @@ static void smc91c111_receive(void *opaque, const uint8_t *buf, int size)
 
     if ((s->rcr & RCR_RXEN) == 0 || (s->rcr & RCR_SOFT_RST))
         return;
-    /* Short packets are padded with zeros.  Recieveing a packet
+    /* Short packets are padded with zeros.  Receiving a packet
        < 64 bytes long is considered an error condition.  */
     if (size < 64)
         packetsize = 64;
diff --git a/tools/ioemu/hw/sparc32_dma.c b/tools/ioemu/hw/sparc32_dma.c
new file mode 100644 (file)
index 0000000..b17a12b
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+ * QEMU Sparc32 DMA controller emulation
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+
+/* debug DMA */
+//#define DEBUG_DMA
+
+/*
+ * This is the DMA controller part of chip STP2000 (Master I/O), also
+ * produced as NCR89C100. See
+ * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C100.txt
+ * and
+ * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/DMA2.txt
+ */
+
+#ifdef DEBUG_DMA
+#define DPRINTF(fmt, args...) \
+do { printf("DMA: " fmt , ##args); } while (0)
+#define pic_set_irq_new(ctl, irq, level)                                \
+    do { printf("DMA: set_irq(%d): %d\n", (irq), (level));              \
+        pic_set_irq_new((ctl), (irq),(level));} while (0)
+#else
+#define DPRINTF(fmt, args...)
+#endif
+
+#define DMA_REGS 8
+#define DMA_MAXADDR (DMA_REGS * 4 - 1)
+
+#define DMA_VER 0xa0000000
+#define DMA_INTR 1
+#define DMA_INTREN 0x10
+#define DMA_WRITE_MEM 0x100
+#define DMA_LOADED 0x04000000
+#define DMA_RESET 0x80
+
+typedef struct DMAState DMAState;
+
+struct DMAState {
+    uint32_t dmaregs[DMA_REGS];
+    int espirq, leirq;
+    void *iommu, *esp_opaque, *lance_opaque, *intctl;
+};
+
+void ledma_set_irq(void *opaque, int isr)
+{
+    DMAState *s = opaque;
+
+    pic_set_irq_new(s->intctl, s->leirq, isr);
+}
+
+/* Note: on sparc, the lance 16 bit bus is swapped */
+void ledma_memory_read(void *opaque, target_phys_addr_t addr, 
+                       uint8_t *buf, int len, int do_bswap)
+{
+    DMAState *s = opaque;
+    int i;
+
+    DPRINTF("DMA write, direction: %c, addr 0x%8.8x\n",
+            s->dmaregs[0] & DMA_WRITE_MEM ? 'w': 'r', s->dmaregs[1]);
+    addr |= s->dmaregs[7];
+    if (do_bswap) {
+        sparc_iommu_memory_read(s->iommu, addr, buf, len);
+    } else {
+        addr &= ~1;
+        len &= ~1;
+        sparc_iommu_memory_read(s->iommu, addr, buf, len);
+        for(i = 0; i < len; i += 2) {
+            bswap16s((uint16_t *)(buf + i));
+        }
+    }
+}
+
+void ledma_memory_write(void *opaque, target_phys_addr_t addr, 
+                        uint8_t *buf, int len, int do_bswap)
+{
+    DMAState *s = opaque;
+    int l, i;
+    uint16_t tmp_buf[32];
+
+    DPRINTF("DMA read, direction: %c, addr 0x%8.8x\n",
+            s->dmaregs[0] & DMA_WRITE_MEM ? 'w': 'r', s->dmaregs[1]);
+    addr |= s->dmaregs[7];
+    if (do_bswap) {
+        sparc_iommu_memory_write(s->iommu, addr, buf, len);
+    } else {
+        addr &= ~1;
+        len &= ~1;
+        while (len > 0) {
+            l = len;
+            if (l > sizeof(tmp_buf))
+                l = sizeof(tmp_buf);
+            for(i = 0; i < l; i += 2) {
+                tmp_buf[i >> 1] = bswap16(*(uint16_t *)(buf + i));
+            }
+            sparc_iommu_memory_write(s->iommu, addr, (uint8_t *)tmp_buf, l);
+            len -= l;
+            buf += l;
+            addr += l;
+        }
+    }
+}
+
+void espdma_raise_irq(void *opaque)
+{
+    DMAState *s = opaque;
+
+    s->dmaregs[0] |= DMA_INTR;
+    pic_set_irq_new(s->intctl, s->espirq, 1);
+}
+
+void espdma_clear_irq(void *opaque)
+{
+    DMAState *s = opaque;
+
+    s->dmaregs[0] &= ~DMA_INTR;
+    pic_set_irq_new(s->intctl, s->espirq, 0);
+}
+
+void espdma_memory_read(void *opaque, uint8_t *buf, int len)
+{
+    DMAState *s = opaque;
+
+    DPRINTF("DMA read, direction: %c, addr 0x%8.8x\n",
+            s->dmaregs[0] & DMA_WRITE_MEM ? 'w': 'r', s->dmaregs[1]);
+    sparc_iommu_memory_read(s->iommu, s->dmaregs[1], buf, len);
+    s->dmaregs[0] |= DMA_INTR;
+    s->dmaregs[1] += len;
+}
+
+void espdma_memory_write(void *opaque, uint8_t *buf, int len)
+{
+    DMAState *s = opaque;
+
+    DPRINTF("DMA write, direction: %c, addr 0x%8.8x\n",
+            s->dmaregs[0] & DMA_WRITE_MEM ? 'w': 'r', s->dmaregs[1]);
+    sparc_iommu_memory_write(s->iommu, s->dmaregs[1], buf, len);
+    s->dmaregs[0] |= DMA_INTR;
+    s->dmaregs[1] += len;
+}
+
+static uint32_t dma_mem_readl(void *opaque, target_phys_addr_t addr)
+{
+    DMAState *s = opaque;
+    uint32_t saddr;
+
+    saddr = (addr & DMA_MAXADDR) >> 2;
+    DPRINTF("read dmareg[%d]: 0x%8.8x\n", saddr, s->dmaregs[saddr]);
+
+    return s->dmaregs[saddr];
+}
+
+static void dma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+    DMAState *s = opaque;
+    uint32_t saddr;
+
+    saddr = (addr & DMA_MAXADDR) >> 2;
+    DPRINTF("write dmareg[%d]: 0x%8.8x -> 0x%8.8x\n", saddr, s->dmaregs[saddr], val);
+    switch (saddr) {
+    case 0:
+        if (!(val & DMA_INTREN))
+            pic_set_irq_new(s->intctl, s->espirq, 0);
+        if (val & DMA_RESET) {
+            esp_reset(s->esp_opaque);
+        } else if (val & 0x40) {
+            val &= ~0x40;
+        } else if (val == 0)
+            val = 0x40;
+        val &= 0x0fffffff;
+        val |= DMA_VER;
+        break;
+    case 1:
+        s->dmaregs[0] |= DMA_LOADED;
+        break;
+    case 4:
+        if (!(val & DMA_INTREN))
+            pic_set_irq_new(s->intctl, s->leirq, 0);
+        if (val & DMA_RESET)
+            pcnet_h_reset(s->lance_opaque);
+        val &= 0x0fffffff;
+        val |= DMA_VER;
+        break;
+    default:
+        break;
+    }
+    s->dmaregs[saddr] = val;
+}
+
+static CPUReadMemoryFunc *dma_mem_read[3] = {
+    dma_mem_readl,
+    dma_mem_readl,
+    dma_mem_readl,
+};
+
+static CPUWriteMemoryFunc *dma_mem_write[3] = {
+    dma_mem_writel,
+    dma_mem_writel,
+    dma_mem_writel,
+};
+
+static void dma_reset(void *opaque)
+{
+    DMAState *s = opaque;
+
+    memset(s->dmaregs, 0, DMA_REGS * 4);
+    s->dmaregs[0] = DMA_VER;
+    s->dmaregs[4] = DMA_VER;
+}
+
+static void dma_save(QEMUFile *f, void *opaque)
+{
+    DMAState *s = opaque;
+    unsigned int i;
+
+    for (i = 0; i < DMA_REGS; i++)
+        qemu_put_be32s(f, &s->dmaregs[i]);
+}
+
+static int dma_load(QEMUFile *f, void *opaque, int version_id)
+{
+    DMAState *s = opaque;
+    unsigned int i;
+
+    if (version_id != 1)
+        return -EINVAL;
+    for (i = 0; i < DMA_REGS; i++)
+        qemu_get_be32s(f, &s->dmaregs[i]);
+
+    return 0;
+}
+
+void *sparc32_dma_init(uint32_t daddr, int espirq, int leirq, void *iommu, void *intctl)
+{
+    DMAState *s;
+    int dma_io_memory;
+
+    s = qemu_mallocz(sizeof(DMAState));
+    if (!s)
+        return NULL;
+
+    s->espirq = espirq;
+    s->leirq = leirq;
+    s->iommu = iommu;
+    s->intctl = intctl;
+
+    dma_io_memory = cpu_register_io_memory(0, dma_mem_read, dma_mem_write, s);
+    cpu_register_physical_memory(daddr, 16 * 2, dma_io_memory);
+
+    register_savevm("sparc32_dma", daddr, 1, dma_save, dma_load, s);
+    qemu_register_reset(dma_reset, s);
+
+    return s;
+}
+
+void sparc32_dma_set_reset_data(void *opaque, void *esp_opaque,
+                                void *lance_opaque)
+{
+    DMAState *s = opaque;
+
+    s->esp_opaque = esp_opaque;
+    s->lance_opaque = lance_opaque;
+}
index 203732f216676b8d767663bd33a833170eeba8f7..9b6aae53c8e373ec889ae9cdc7129f70dd2d37f7 100644 (file)
 #define PHYS_JJ_IOMMU  0x10000000      /* I/O MMU */
 #define PHYS_JJ_TCX_FB 0x50000000      /* TCX frame buffer */
 #define PHYS_JJ_SLAVIO 0x70000000      /* Slavio base */
-#define PHYS_JJ_ESPDMA  0x78400000      /* ESP DMA controller */
+#define PHYS_JJ_DMA     0x78400000      /* DMA controller */
 #define PHYS_JJ_ESP     0x78800000      /* ESP SCSI */
 #define PHYS_JJ_ESP_IRQ    18
-#define PHYS_JJ_LEDMA   0x78400010      /* Lance DMA controller */
 #define PHYS_JJ_LE      0x78C00000      /* Lance ethernet */
 #define PHYS_JJ_LE_IRQ     16
 #define PHYS_JJ_CLOCK  0x71D00000      /* Per-CPU timer/counter, L14 */
@@ -56,6 +55,9 @@
 #define PHYS_JJ_FDC    0x71400000      /* Floppy */
 #define PHYS_JJ_FLOPPY_IRQ 22
 #define PHYS_JJ_ME_IRQ 30              /* Module error, power fail */
+#define PHYS_JJ_CS      0x6c000000      /* Crystal CS4231 */
+#define PHYS_JJ_CS_IRQ  5
+
 #define MAX_CPUS 16
 
 /* TSC handling */
@@ -192,13 +194,6 @@ void pic_set_irq_cpu(int irq, int level, unsigned int cpu)
     slavio_pic_set_irq_cpu(slavio_intctl, irq, level, cpu);
 }
 
-static void *iommu;
-
-uint32_t iommu_translate(uint32_t addr)
-{
-    return iommu_translate_local(iommu, addr);
-}
-
 static void *slavio_misc;
 
 void qemu_system_powerdown(void)
@@ -223,6 +218,7 @@ static void sun4m_init(int ram_size, int vga_ram_size, int boot_device,
     int ret, linux_boot;
     unsigned int i;
     long vram_size = 0x100000, prom_offset, initrd_size, kernel_size;
+    void *iommu, *dma, *main_esp, *main_lance = NULL;
 
     linux_boot = (kernel_filename != NULL);
 
@@ -243,12 +239,13 @@ static void sun4m_init(int ram_size, int vga_ram_size, int boot_device,
     for(i = 0; i < smp_cpus; i++) {
         slavio_intctl_set_cpu(slavio_intctl, i, envs[i]);
     }
+    dma = sparc32_dma_init(PHYS_JJ_DMA, PHYS_JJ_ESP_IRQ, PHYS_JJ_LE_IRQ, iommu, slavio_intctl);
 
     tcx_init(ds, PHYS_JJ_TCX_FB, phys_ram_base + ram_size, ram_size, vram_size, graphic_width, graphic_height);
     if (nd_table[0].vlan) {
         if (nd_table[0].model == NULL
             || strcmp(nd_table[0].model, "lance") == 0) {
-            lance_init(&nd_table[0], PHYS_JJ_LE_IRQ, PHYS_JJ_LE, PHYS_JJ_LEDMA);
+            main_lance = lance_init(&nd_table[0], PHYS_JJ_LE, dma);
         } else {
             fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
             exit (1);
@@ -264,8 +261,17 @@ static void sun4m_init(int ram_size, int vga_ram_size, int boot_device,
     // Slavio TTYB (base+0, Linux ttyS1) is the second Qemu serial device
     slavio_serial_init(PHYS_JJ_SER, PHYS_JJ_SER_IRQ, serial_hds[1], serial_hds[0]);
     fdctrl_init(PHYS_JJ_FLOPPY_IRQ, 0, 1, PHYS_JJ_FDC, fd_table);
-    esp_init(bs_table, PHYS_JJ_ESP_IRQ, PHYS_JJ_ESP, PHYS_JJ_ESPDMA);
+    main_esp = esp_init(bs_table, PHYS_JJ_ESP, dma);
+
+    for (i = 0; i < MAX_DISKS; i++) {
+        if (bs_table[i]) {
+            esp_scsi_attach(main_esp, bs_table[i], i);
+        }
+    }
+
     slavio_misc = slavio_misc_init(PHYS_JJ_SLAVIO, PHYS_JJ_ME_IRQ);
+    cs_init(PHYS_JJ_CS, PHYS_JJ_CS_IRQ, slavio_intctl);
+    sparc32_dma_set_reset_data(dma, main_esp, main_lance);
 
     prom_offset = ram_size + vram_size;
     cpu_register_physical_memory(PROM_ADDR, 
index 6d413691dbfea57d35c14f33db45ff165beaa41c..61069a6529c2ded351256c9c9524f5d5a3b4aa2b 100644 (file)
@@ -344,7 +344,7 @@ static void sun4u_init(int ram_size, int vga_ram_size, int boot_device,
     for(i = 0; i < nb_nics; i++) {
         if (!nd_table[i].model)
             nd_table[i].model = "ne2k_pci";
-       pci_nic_init(pci_bus, &nd_table[i]);
+       pci_nic_init(pci_bus, &nd_table[i], -1);
     }
 
     pci_cmd646_ide_init(pci_bus, bs_table, 1);
index a3a2114e8f65f28ba2127d5ded2bb5733c2b65c5..a1a6b68559d73730fca0c0922c889b15df250718 100644 (file)
@@ -31,40 +31,81 @@ typedef struct TCXState {
     uint32_t addr;
     DisplayState *ds;
     uint8_t *vram;
-    unsigned long vram_offset;
+    ram_addr_t vram_offset;
     uint16_t width, height;
     uint8_t r[256], g[256], b[256];
+    uint32_t palette[256];
     uint8_t dac_index, dac_state;
 } TCXState;
 
 static void tcx_screen_dump(void *opaque, const char *filename);
 
+/* XXX: unify with vga draw line functions */
+static inline unsigned int rgb_to_pixel8(unsigned int r, unsigned int g, unsigned b)
+{
+    return ((r >> 5) << 5) | ((g >> 5) << 2) | (b >> 6);
+}
+
+static inline unsigned int rgb_to_pixel15(unsigned int r, unsigned int g, unsigned b)
+{
+    return ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
+}
+
+static inline unsigned int rgb_to_pixel16(unsigned int r, unsigned int g, unsigned b)
+{
+    return ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
+}
+
+static inline unsigned int rgb_to_pixel32(unsigned int r, unsigned int g, unsigned b)
+{
+    return (r << 16) | (g << 8) | b;
+}
+
+static void update_palette_entries(TCXState *s, int start, int end)
+{
+    int i;
+    for(i = start; i < end; i++) {
+        switch(s->ds->depth) {
+        default:
+        case 8:
+            s->palette[i] = rgb_to_pixel8(s->r[i], s->g[i], s->b[i]);
+            break;
+        case 15:
+            s->palette[i] = rgb_to_pixel15(s->r[i], s->g[i], s->b[i]);
+            break;
+        case 16:
+            s->palette[i] = rgb_to_pixel16(s->r[i], s->g[i], s->b[i]);
+            break;
+        case 32:
+            s->palette[i] = rgb_to_pixel32(s->r[i], s->g[i], s->b[i]);
+            break;
+        }
+    }
+}
+
 static void tcx_draw_line32(TCXState *s1, uint8_t *d, 
                            const uint8_t *s, int width)
 {
     int x;
     uint8_t val;
+    uint32_t *p = (uint32_t *)d;
 
     for(x = 0; x < width; x++) {
        val = *s++;
-       *d++ = s1->b[val];
-       *d++ = s1->g[val];
-       *d++ = s1->r[val];
-       d++;
+        *p++ = s1->palette[val];
     }
 }
 
-static void tcx_draw_line24(TCXState *s1, uint8_t *d, 
+static void tcx_draw_line16(TCXState *s1, uint8_t *d, 
                            const uint8_t *s, int width)
 {
     int x;
     uint8_t val;
+    uint16_t *p = (uint16_t *)d;
 
     for(x = 0; x < width; x++) {
        val = *s++;
-       *d++ = s1->b[val];
-       *d++ = s1->g[val];
-       *d++ = s1->r[val];
+        *p++ = s1->palette[val];
     }
 }
 
@@ -76,8 +117,7 @@ static void tcx_draw_line8(TCXState *s1, uint8_t *d,
 
     for(x = 0; x < width; x++) {
        val = *s++;
-       /* XXX translate between palettes? */
-       *d++ = val;
+        *d++ = s1->palette[val];
     }
 }
 
@@ -86,8 +126,8 @@ static void tcx_draw_line8(TCXState *s1, uint8_t *d,
 static void tcx_update_display(void *opaque)
 {
     TCXState *ts = opaque;
-    uint32_t page;
-    int y, page_min, page_max, y_start, dd, ds;
+    ram_addr_t page, page_min, page_max;
+    int y, y_start, dd, ds;
     uint8_t *d, *s;
     void (*f)(TCXState *s1, uint8_t *d, const uint8_t *s, int width);
 
@@ -95,8 +135,8 @@ static void tcx_update_display(void *opaque)
        return;
     page = ts->vram_offset;
     y_start = -1;
-    page_min = 0x7fffffff;
-    page_max = -1;
+    page_min = 0xffffffff;
+    page_max = 0;
     d = ts->ds->data;
     s = ts->vram;
     dd = ts->ds->linesize;
@@ -106,8 +146,9 @@ static void tcx_update_display(void *opaque)
     case 32:
        f = tcx_draw_line32;
        break;
-    case 24:
-       f = tcx_draw_line24;
+    case 15:
+    case 16:
+       f = tcx_draw_line16;
        break;
     default:
     case 8:
@@ -154,7 +195,7 @@ static void tcx_update_display(void *opaque)
                   ts->width, y - y_start);
     }
     /* reset modified pages */
-    if (page_max != -1) {
+    if (page_min <= page_max) {
         cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
                                         VGA_DIRTY_FLAG);
     }
@@ -201,6 +242,7 @@ static int tcx_load(QEMUFile *f, void *opaque, int version_id)
     qemu_get_buffer(f, s->b, 256);
     qemu_get_8s(f, &s->dac_index);
     qemu_get_8s(f, &s->dac_state);
+    update_palette_entries(s, 0, 256);
     return 0;
 }
 
@@ -213,6 +255,7 @@ static void tcx_reset(void *opaque)
     memset(s->g, 0, 256);
     memset(s->b, 0, 256);
     s->r[255] = s->g[255] = s->b[255] = 255;
+    update_palette_entries(s, 0, 256);
     memset(s->vram, 0, MAXX*MAXY);
     cpu_physical_memory_reset_dirty(s->vram_offset, s->vram_offset + MAXX*MAXY,
                                     VGA_DIRTY_FLAG);
@@ -240,14 +283,17 @@ static void tcx_dac_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
        switch (s->dac_state) {
        case 0:
            s->r[s->dac_index] = val >> 24;
+            update_palette_entries(s, s->dac_index, s->dac_index + 1);
            s->dac_state++;
            break;
        case 1:
            s->g[s->dac_index] = val >> 24;
+            update_palette_entries(s, s->dac_index, s->dac_index + 1);
            s->dac_state++;
            break;
        case 2:
            s->b[s->dac_index] = val >> 24;
+            update_palette_entries(s, s->dac_index, s->dac_index + 1);
        default:
            s->dac_state = 0;
            break;
index a7e36000472d21272ed2da4891f8ed417d1dbfeb..6448a6f25086fc4174ad7fc57fd2cc64dbd9c9e3 100644 (file)
@@ -140,9 +140,15 @@ static CPUReadMemoryFunc *pci_unin_read[] = {
 };
 #endif
 
-static void pci_unin_set_irq(PCIDevice *d, void *pic, int irq_num, int level)
+/* Don't know if this matches real hardware, but it agrees with OHW.  */
+static int pci_unin_map_irq(PCIDevice *pci_dev, int irq_num)
 {
-    openpic_set_irq(pic, d->config[PCI_INTERRUPT_LINE], level);
+    return (irq_num + (pci_dev->devfn >> 3)) & 3;
+}
+
+static void pci_unin_set_irq(void *pic, int irq_num, int level)
+{
+    openpic_set_irq(pic, irq_num + 8, level);
 }
 
 PCIBus *pci_pmac_init(void *pic)
@@ -154,7 +160,8 @@ PCIBus *pci_pmac_init(void *pic)
     /* Use values found on a real PowerMac */
     /* Uninorth main bus */
     s = qemu_mallocz(sizeof(UNINState));
-    s->bus = pci_register_bus(pci_unin_set_irq, NULL, 11 << 3);
+    s->bus = pci_register_bus(pci_unin_set_irq, pci_unin_map_irq,
+                              pic, 11 << 3, 4);
 
     pci_mem_config = cpu_register_io_memory(0, pci_unin_main_config_read, 
                                             pci_unin_main_config_write, s);
@@ -176,7 +183,7 @@ PCIBus *pci_pmac_init(void *pic)
     d->config[0x0E] = 0x00; // header_type
     d->config[0x34] = 0x00; // capabilities_pointer
 
-#if 0 // XXX: not activated as PPC BIOS doesn't handle mutiple buses properly
+#if 0 // XXX: not activated as PPC BIOS doesn't handle multiple buses properly
     /* pci-to-pci bridge */
     d = pci_register_device("Uni-north bridge", sizeof(PCIDevice), 0, 13 << 3,
                             NULL, NULL);
index c7af3d65abb3aa8ebd3590321af582a02e0e3ad3..e9479773134e98175829de8a2f6821e46b1850ed 100644 (file)
@@ -40,6 +40,7 @@ typedef struct USBMouseState {
     int kind;
     int mouse_grabbed;
     int status_changed;
+    QEMUPutMouseEntry *eh_entry;
 } USBMouseState;
 
 /* mostly the same values as the Bochs USB Mouse device */
@@ -262,7 +263,8 @@ static int usb_mouse_poll(USBMouseState *s, uint8_t *buf, int len)
     int dx, dy, dz, b, l;
 
     if (!s->mouse_grabbed) {
-       qemu_add_mouse_event_handler(usb_mouse_event, s, 0);
+       s->eh_entry = qemu_add_mouse_event_handler(usb_mouse_event, s,
+                                                  0, "QEMU USB Mouse");
        s->mouse_grabbed = 1;
     }
     
@@ -298,7 +300,8 @@ static int usb_tablet_poll(USBMouseState *s, uint8_t *buf, int len)
     int dz, b, l;
 
     if (!s->mouse_grabbed) {
-       qemu_add_mouse_event_handler(usb_tablet_event, s, 1);
+       s->eh_entry = qemu_add_mouse_event_handler(usb_tablet_event, s,
+                                                  1, "QEMU USB Tablet");
        s->mouse_grabbed = 1;
     }
     
@@ -477,19 +480,18 @@ static int usb_mouse_handle_control(USBDevice *dev, int request, int value,
     return ret;
 }
 
-static int usb_mouse_handle_data(USBDevice *dev, int pid, 
-                                 uint8_t devep, uint8_t *data, int len)
+static int usb_mouse_handle_data(USBDevice *dev, USBPacket *p)
 {
     USBMouseState *s = (USBMouseState *)dev;
     int ret = 0;
 
-    switch(pid) {
+    switch(p->pid) {
     case USB_TOKEN_IN:
-        if (devep == 1) {
+        if (p->devep == 1) {
             if (s->kind == USB_MOUSE)
-                ret = usb_mouse_poll(s, data, len);
+                ret = usb_mouse_poll(s, p->data, p->len);
             else if (s->kind == USB_TABLET)
-                ret = usb_tablet_poll(s, data, len);
+                ret = usb_tablet_poll(s, p->data, p->len);
 
             if (!s->status_changed)
                 ret = USB_RET_NAK;
@@ -513,7 +515,7 @@ static void usb_mouse_handle_destroy(USBDevice *dev)
 {
     USBMouseState *s = (USBMouseState *)dev;
 
-    qemu_add_mouse_event_handler(NULL, NULL, 0);
+    qemu_remove_mouse_event_handler(s->eh_entry);
     qemu_free(s);
 }
 
@@ -552,11 +554,13 @@ int usb_mouse_load(QEMUFile *f, void *opaque, int version_id)
 
     if ( s->kind == USB_TABLET) {
         fprintf(logfile, "usb_mouse_load:add usb_tablet_event.\n");
-        qemu_add_mouse_event_handler(usb_tablet_event, s, 1);
+        qemu_add_mouse_event_handler(usb_tablet_event, s, 1, "QEMU USB Tablet");
     } else if ( s->kind == USB_MOUSE) {
         fprintf(logfile, "usb_mouse_load:add usb_mouse_event.\n");
-        qemu_add_mouse_event_handler(usb_mouse_event, s, 0);
+        qemu_add_mouse_event_handler(usb_mouse_event, s, 0, "QEMU USB MOUSE");
     }
+
+    return 0;
 }
 
 
index 8350931be639406bb322ec8346c95c929e4a1a4c..651dac21091feaddd6c37798a5168d3431cf66e2 100644 (file)
@@ -180,8 +180,7 @@ static void usb_hub_attach(USBPort *port1, USBDevice *dev)
             port->wPortStatus &= ~PORT_STAT_LOW_SPEED;
         port->port.dev = dev;
         /* send the attach message */
-        dev->handle_packet(dev, 
-                           USB_MSG_ATTACH, 0, 0, NULL, 0);
+        usb_send_msg(dev, USB_MSG_ATTACH);
     } else {
         dev = port->port.dev;
         if (dev) {
@@ -192,8 +191,7 @@ static void usb_hub_attach(USBPort *port1, USBDevice *dev)
                 port->wPortChange |= PORT_STAT_C_ENABLE;
             }
             /* send the detach message */
-            dev->handle_packet(dev, 
-                               USB_MSG_DETACH, 0, 0, NULL, 0);
+            usb_send_msg(dev, USB_MSG_DETACH);
             port->port.dev = NULL;
         }
     }
@@ -349,8 +347,7 @@ static int usb_hub_handle_control(USBDevice *dev, int request, int value,
                 break;
             case PORT_RESET:
                 if (dev) {
-                    dev->handle_packet(dev, 
-                                       USB_MSG_RESET, 0, 0, NULL, 0);
+                    usb_send_msg(dev, USB_MSG_RESET);
                     port->wPortChange |= PORT_STAT_C_RESET;
                     /* set enable bit */
                     port->wPortStatus |= PORT_STAT_ENABLE;
@@ -434,22 +431,21 @@ static int usb_hub_handle_control(USBDevice *dev, int request, int value,
     return ret;
 }
 
-static int usb_hub_handle_data(USBDevice *dev, int pid, 
-                               uint8_t devep, uint8_t *data, int len)
+static int usb_hub_handle_data(USBDevice *dev, USBPacket *p)
 {
     USBHubState *s = (USBHubState *)dev;
     int ret;
 
-    switch(pid) {
+    switch(p->pid) {
     case USB_TOKEN_IN:
-        if (devep == 1) {
+        if (p->devep == 1) {
             USBHubPort *port;
             unsigned int status;
             int i, n;
             n = (s->nb_ports + 1 + 7) / 8;
-            if (len == 1) { /* FreeBSD workaround */
+            if (p->len == 1) { /* FreeBSD workaround */
                 n = 1;
-            } else if (n > len) {
+            } else if (n > p->len) {
                 return USB_RET_BABBLE;
             }
             status = 0;
@@ -460,7 +456,7 @@ static int usb_hub_handle_data(USBDevice *dev, int pid,
             }
             if (status != 0) {
                 for(i = 0; i < n; i++) {
-                    data[i] = status >> (8 * i);
+                    p->data[i] = status >> (8 * i);
                 }
                 ret = n;
             } else {
@@ -479,9 +475,7 @@ static int usb_hub_handle_data(USBDevice *dev, int pid,
     return ret;
 }
 
-static int usb_hub_broadcast_packet(USBHubState *s, int pid, 
-                                    uint8_t devaddr, uint8_t devep,
-                                    uint8_t *data, int len)
+static int usb_hub_broadcast_packet(USBHubState *s, USBPacket *p)
 {
     USBHubPort *port;
     USBDevice *dev;
@@ -491,9 +485,7 @@ static int usb_hub_broadcast_packet(USBHubState *s, int pid,
         port = &s->ports[i];
         dev = port->port.dev;
         if (dev && (port->wPortStatus & PORT_STAT_ENABLE)) {
-            ret = dev->handle_packet(dev, pid, 
-                                     devaddr, devep,
-                                     data, len);
+            ret = dev->handle_packet(dev, p);
             if (ret != USB_RET_NODEV) {
                 return ret;
             }
@@ -502,9 +494,7 @@ static int usb_hub_broadcast_packet(USBHubState *s, int pid,
     return USB_RET_NODEV;
 }
 
-static int usb_hub_handle_packet(USBDevice *dev, int pid, 
-                                 uint8_t devaddr, uint8_t devep,
-                                 uint8_t *data, int len)
+static int usb_hub_handle_packet(USBDevice *dev, USBPacket *p)
 {
     USBHubState *s = (USBHubState *)dev;
 
@@ -513,14 +503,14 @@ static int usb_hub_handle_packet(USBDevice *dev, int pid,
 #endif
     if (dev->state == USB_STATE_DEFAULT &&
         dev->addr != 0 &&
-        devaddr != dev->addr &&
-        (pid == USB_TOKEN_SETUP || 
-         pid == USB_TOKEN_OUT || 
-         pid == USB_TOKEN_IN)) {
+        p->devaddr != dev->addr &&
+        (p->pid == USB_TOKEN_SETUP || 
+         p->pid == USB_TOKEN_OUT || 
+         p->pid == USB_TOKEN_IN)) {
         /* broadcast the packet to the devices */
-        return usb_hub_broadcast_packet(s, pid, devaddr, devep, data, len);
+        return usb_hub_broadcast_packet(s, p);
     }
-    return usb_generic_handle_packet(dev, pid, devaddr, devep, data, len);
+    return usb_generic_handle_packet(dev, p);
 }
 
 static void usb_hub_handle_destroy(USBDevice *dev)
index ff2047d4b2b9518ef1f1f2876197cc9769a5b668..4530a1ceaaf8e236ac03d44a9bc350a6fa57309a 100644 (file)
@@ -32,12 +32,37 @@ enum USBMSDMode {
 typedef struct {
     USBDevice dev;
     enum USBMSDMode mode;
+    uint32_t scsi_len;
+    uint8_t *scsi_buf;
+    uint32_t usb_len;
+    uint8_t *usb_buf;
     uint32_t data_len;
+    uint32_t residue;
     uint32_t tag;
+    BlockDriverState *bs;
     SCSIDevice *scsi_dev;
     int result;
+    /* For async completion.  */
+    USBPacket *packet;
 } MSDState;
 
+struct usb_msd_cbw {
+    uint32_t sig;
+    uint32_t tag;
+    uint32_t data_len;
+    uint8_t flags;
+    uint8_t lun;
+    uint8_t cmd_len;
+    uint8_t cmd[16];
+};
+
+struct usb_msd_csw {
+    uint32_t sig;
+    uint32_t tag;
+    uint32_t residue;
+    uint8_t status;
+};
+
 static const uint8_t qemu_msd_dev_descriptor[] = {
        0x12,       /*  u8 bLength; */
        0x01,       /*  u8 bDescriptorType; Device */
@@ -103,13 +128,91 @@ static const uint8_t qemu_msd_config_descriptor[] = {
        0x00        /*  u8  ep_bInterval; */
 };
 
-static void usb_msd_command_complete(void *opaque, uint32_t tag, int fail)
+static void usb_msd_copy_data(MSDState *s)
+{
+    uint32_t len;
+    len = s->usb_len;
+    if (len > s->scsi_len)
+        len = s->scsi_len;
+    if (s->mode == USB_MSDM_DATAIN) {
+        memcpy(s->usb_buf, s->scsi_buf, len);
+    } else {
+        memcpy(s->scsi_buf, s->usb_buf, len);
+    }
+    s->usb_len -= len;
+    s->scsi_len -= len;
+    s->usb_buf += len;
+    s->scsi_buf += len;
+    s->data_len -= len;
+    if (s->scsi_len == 0) {
+        if (s->mode == USB_MSDM_DATAIN) {
+            scsi_read_data(s->scsi_dev, s->tag);
+        } else if (s->mode == USB_MSDM_DATAOUT) {
+            scsi_write_data(s->scsi_dev, s->tag);
+        }
+    }
+}
+
+static void usb_msd_send_status(MSDState *s)
+{
+    struct usb_msd_csw csw;
+
+    csw.sig = cpu_to_le32(0x53425355);
+    csw.tag = cpu_to_le32(s->tag);
+    csw.residue = s->residue;
+    csw.status = s->result;
+    memcpy(s->usb_buf, &csw, 13);
+}
+
+static void usb_msd_command_complete(void *opaque, int reason, uint32_t tag,
+                                     uint32_t arg)
 {
     MSDState *s = (MSDState *)opaque;
+    USBPacket *p = s->packet;
 
-    DPRINTF("Command complete\n");
-    s->result = fail;
-    s->mode = USB_MSDM_CSW;
+    if (tag != s->tag) {
+        fprintf(stderr, "usb-msd: Unexpected SCSI Tag 0x%x\n", tag);
+    }
+    if (reason == SCSI_REASON_DONE) {
+        DPRINTF("Command complete %d\n", arg);
+        s->residue = s->data_len;
+        s->result = arg != 0;
+        if (s->packet) {
+            if (s->data_len == 0 && s->mode == USB_MSDM_DATAOUT) {
+                /* A deferred packet with no write data remaining must be
+                   the status read packet.  */
+                usb_msd_send_status(s);
+                s->mode = USB_MSDM_CBW;
+            } else {
+                if (s->data_len) {
+                    s->data_len -= s->usb_len;
+                    if (s->mode == USB_MSDM_DATAIN)
+                        memset(s->usb_buf, 0, s->usb_len);
+                    s->usb_len = 0;
+                }
+                if (s->data_len == 0)
+                    s->mode = USB_MSDM_CSW;
+            }
+            s->packet = NULL;
+            usb_packet_complete(p);
+        } else if (s->data_len == 0) {
+            s->mode = USB_MSDM_CSW;
+        }
+        return;
+    }
+    s->scsi_len = arg;
+    s->scsi_buf = scsi_get_buf(s->scsi_dev, tag);
+    if (p) {
+        usb_msd_copy_data(s);
+        if (s->usb_len == 0) {
+            /* Set s->packet to NULL before calling usb_packet_complete
+               because annother request may be issued before
+               usb_packet_complete returns.  */
+            DPRINTF("Packet complete %p\n", p);
+            s->packet = NULL;
+            usb_packet_complete(p);
+        }
+    }
 }
 
 static void usb_msd_handle_reset(USBDevice *dev)
@@ -233,32 +336,24 @@ static int usb_msd_handle_control(USBDevice *dev, int request, int value,
     return ret;
 }
 
-struct usb_msd_cbw {
-    uint32_t sig;
-    uint32_t tag;
-    uint32_t data_len;
-    uint8_t flags;
-    uint8_t lun;
-    uint8_t cmd_len;
-    uint8_t cmd[16];
-};
-
-struct usb_msd_csw {
-    uint32_t sig;
-    uint32_t tag;
-    uint32_t residue;
-    uint8_t status;
-};
+static void usb_msd_cancel_io(USBPacket *p, void *opaque)
+{
+    MSDState *s = opaque;
+    scsi_cancel_io(s->scsi_dev, s->tag);
+    s->packet = NULL;
+    s->scsi_len = 0;
+}
 
-static int usb_msd_handle_data(USBDevice *dev, int pid, uint8_t devep,
-                               uint8_t *data, int len)
+static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
 {
     MSDState *s = (MSDState *)dev;
     int ret = 0;
     struct usb_msd_cbw cbw;
-    struct usb_msd_csw csw;
+    uint8_t devep = p->devep;
+    uint8_t *data = p->data;
+    int len = p->len;
 
-    switch (pid) {
+    switch (p->pid) {
     case USB_TOKEN_OUT:
         if (devep != 2)
             goto fail;
@@ -291,7 +386,17 @@ static int usb_msd_handle_data(USBDevice *dev, int pid, uint8_t devep,
             }
             DPRINTF("Command tag 0x%x flags %08x len %d data %d\n",
                     s->tag, cbw.flags, cbw.cmd_len, s->data_len);
+            s->residue = 0;
             scsi_send_command(s->scsi_dev, s->tag, cbw.cmd, 0);
+            /* ??? Should check that USB and SCSI data transfer
+               directions match.  */
+            if (s->residue == 0) {
+                if (s->mode == USB_MSDM_DATAIN) {
+                    scsi_read_data(s->scsi_dev, s->tag);
+                } else if (s->mode == USB_MSDM_DATAOUT) {
+                    scsi_write_data(s->scsi_dev, s->tag);
+                }
+            }
             ret = len;
             break;
 
@@ -300,13 +405,25 @@ static int usb_msd_handle_data(USBDevice *dev, int pid, uint8_t devep,
             if (len > s->data_len)
                 goto fail;
 
-            if (scsi_write_data(s->scsi_dev, data, len))
-                goto fail;
-
-            s->data_len -= len;
-            if (s->data_len == 0)
-                s->mode = USB_MSDM_CSW;
-            ret = len;
+            s->usb_buf = data;
+            s->usb_len = len;
+            if (s->scsi_len) {
+                usb_msd_copy_data(s);
+            }
+            if (s->residue && s->usb_len) {
+                s->data_len -= s->usb_len;
+                if (s->data_len == 0)
+                    s->mode = USB_MSDM_CSW;
+                s->usb_len = 0;
+            }
+            if (s->usb_len) {
+                DPRINTF("Deferring packet %p\n", p);
+                usb_defer_packet(p, usb_msd_cancel_io, s);
+                s->packet = p;
+                ret = USB_RET_ASYNC;
+            } else {
+                ret = len;
+            }
             break;
 
         default:
@@ -320,33 +437,52 @@ static int usb_msd_handle_data(USBDevice *dev, int pid, uint8_t devep,
             goto fail;
 
         switch (s->mode) {
+        case USB_MSDM_DATAOUT:
+            if (s->data_len != 0 || len < 13)
+                goto fail;
+            /* Waiting for SCSI write to complete.  */
+            usb_defer_packet(p, usb_msd_cancel_io, s);
+            s->packet = p;
+            ret = USB_RET_ASYNC;
+            break;
+
         case USB_MSDM_CSW:
             DPRINTF("Command status %d tag 0x%x, len %d\n",
                     s->result, s->tag, len);
             if (len < 13)
                 goto fail;
 
-            csw.sig = cpu_to_le32(0x53425355);
-            csw.tag = cpu_to_le32(s->tag);
-            csw.residue = 0;
-            csw.status = s->result;
-            memcpy(data, &csw, 13);
-            ret = 13;
+            s->usb_len = len;
+            s->usb_buf = data;
+            usb_msd_send_status(s);
             s->mode = USB_MSDM_CBW;
+            ret = 13;
             break;
 
         case USB_MSDM_DATAIN:
             DPRINTF("Data in %d/%d\n", len, s->data_len);
             if (len > s->data_len)
                 len = s->data_len;
-
-            if (scsi_read_data(s->scsi_dev, data, len))
-                goto fail;
-
-            s->data_len -= len;
-            if (s->data_len == 0)
-                s->mode = USB_MSDM_CSW;
-            ret = len;
+            s->usb_buf = data;
+            s->usb_len = len;
+            if (s->scsi_len) {
+                usb_msd_copy_data(s);
+            }
+            if (s->residue && s->usb_len) {
+                s->data_len -= s->usb_len;
+                memset(s->usb_buf, 0, s->usb_len);
+                if (s->data_len == 0)
+                    s->mode = USB_MSDM_CSW;
+                s->usb_len = 0;
+            }
+            if (s->usb_len) {
+                DPRINTF("Deferring packet %p\n", p);
+                usb_defer_packet(p, usb_msd_cancel_io, s);
+                s->packet = p;
+                ret = USB_RET_ASYNC;
+            } else {
+                ret = len;
+            }
             break;
 
         default:
@@ -370,6 +506,7 @@ static void usb_msd_handle_destroy(USBDevice *dev)
     MSDState *s = (MSDState *)dev;
 
     scsi_disk_destroy(s->scsi_dev);
+    bdrv_delete(s->bs);
     qemu_free(s);
 }
 
@@ -383,7 +520,9 @@ USBDevice *usb_msd_init(const char *filename)
         return NULL;
 
     bdrv = bdrv_new("usb");
-    bdrv_open(bdrv, filename, 0);
+    if (bdrv_open(bdrv, filename, 0) < 0)
+        goto fail;
+    s->bs = bdrv;
 
     s->dev.speed = USB_SPEED_FULL;
     s->dev.handle_packet = usb_generic_handle_packet;
@@ -396,7 +535,10 @@ USBDevice *usb_msd_init(const char *filename)
     snprintf(s->dev.devname, sizeof(s->dev.devname), "QEMU USB MSD(%.16s)",
              filename);
 
-    s->scsi_dev = scsi_disk_init(bdrv, usb_msd_command_complete, s);
+    s->scsi_dev = scsi_disk_init(bdrv, 0, usb_msd_command_complete, s);
     usb_msd_handle_reset((USBDevice *)s);
     return (USBDevice *)s;
+ fail:
+    qemu_free(s);
+    return NULL;
 }
index a56326267621a8b09131b0852b321d78fa41c3a3..e58829fd9a7cc52183f196d05e1ab21106113ccd 100644 (file)
@@ -89,6 +89,14 @@ typedef struct {
     uint32_t rhdesc_a, rhdesc_b;
     uint32_t rhstatus;
     OHCIPort rhport[OHCI_MAX_PORTS];
+
+    /* Active packets.  */
+    uint32_t old_ctl;
+    USBPacket usb_packet;
+    uint8_t usb_buf[8192];
+    uint32_t async_td;
+    int async_complete;
+
 } OHCIState;
 
 /* Host Controller Communications Area */
@@ -288,8 +296,7 @@ static void ohci_attach(USBPort *port1, USBDevice *dev)
             port->ctrl &= ~OHCI_PORT_LSDA;
         port->port.dev = dev;
         /* send the attach message */
-        dev->handle_packet(dev, 
-                           USB_MSG_ATTACH, 0, 0, NULL, 0);
+        usb_send_msg(dev, USB_MSG_ATTACH);
         dprintf("usb-ohci: Attached port %d\n", port1->index);
     } else {
         /* set connect status */
@@ -305,8 +312,7 @@ static void ohci_attach(USBPort *port1, USBDevice *dev)
         dev = port->port.dev;
         if (dev) {
             /* send the detach message */
-            dev->handle_packet(dev, 
-                               USB_MSG_DETACH, 0, 0, NULL, 0);
+            usb_send_msg(dev, USB_MSG_DETACH);
         }
         port->port.dev = NULL;
         dprintf("usb-ohci: Detached port %d\n", port1->index);
@@ -323,6 +329,7 @@ static void ohci_reset(OHCIState *ohci)
     int i;
 
     ohci->ctl = 0;
+    ohci->old_ctl = 0;
     ohci->status = 0;
     ohci->intr_status = 0;
     ohci->intr = OHCI_INTR_MIE;
@@ -356,6 +363,10 @@ static void ohci_reset(OHCIState *ohci)
         if (port->port.dev)
             ohci_attach(&port->port, port->port.dev);
       }
+    if (ohci->async_td) {
+        usb_cancel_packet(&ohci->usb_packet);
+        ohci->async_td = 0;
+    }
     dprintf("usb-ohci: Reset %s\n", ohci->pci_dev.name);
 }
 
@@ -423,6 +434,18 @@ static void ohci_copy_td(struct ohci_td *td, uint8_t *buf, int len, int write)
     cpu_physical_memory_rw(ptr, buf, len - n, write);
 }
 
+static void ohci_process_lists(OHCIState *ohci);
+
+static void ohci_async_complete_packet(USBPacket * packet, void *opaque)
+{
+    OHCIState *ohci = opaque;
+#ifdef DEBUG_PACKET
+    dprintf("Async packet complete\n");
+#endif
+    ohci->async_complete = 1;
+    ohci_process_lists(ohci);
+}
+
 /* Service a transport descriptor.
    Returns nonzero to terminate processing of this endpoint.  */
 
@@ -430,7 +453,6 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
 {
     int dir;
     size_t len = 0;
-    uint8_t buf[8192];
     char *str = NULL;
     int pid;
     int ret;
@@ -439,8 +461,17 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
     struct ohci_td td;
     uint32_t addr;
     int flag_r;
+    int completion;
 
     addr = ed->head & OHCI_DPTR_MASK;
+    /* See if this TD has already been submitted to the device.  */
+    completion = (addr == ohci->async_td);
+    if (completion && !ohci->async_complete) {
+#ifdef DEBUG_PACKET
+        dprintf("Skipping async TD\n");
+#endif
+        return 1;
+    }
     if (!ohci_read_td(addr, &td)) {
         fprintf(stderr, "usb-ohci: TD read error at %x\n", addr);
         return 0;
@@ -481,8 +512,8 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
             len = (td.be - td.cbp) + 1;
         }
 
-        if (len && dir != OHCI_TD_DIR_IN) {
-            ohci_copy_td(&td, buf, len, 0);
+        if (len && dir != OHCI_TD_DIR_IN && !completion) {
+            ohci_copy_td(&td, ohci->usb_buf, len, 0);
         }
     }
 
@@ -494,31 +525,58 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
     if (len >= 0 && dir != OHCI_TD_DIR_IN) {
         dprintf("  data:");
         for (i = 0; i < len; i++)
-            printf(" %.2x", buf[i]);
+            printf(" %.2x", ohci->usb_buf[i]);
         dprintf("\n");
     }
 #endif
-    ret = USB_RET_NODEV;
-    for (i = 0; i < ohci->num_ports; i++) {
-        dev = ohci->rhport[i].port.dev;
-        if ((ohci->rhport[i].ctrl & OHCI_PORT_PES) == 0)
-            continue;
-
-        ret = dev->handle_packet(dev, pid, OHCI_BM(ed->flags, ED_FA),
-                                 OHCI_BM(ed->flags, ED_EN), buf, len);
-        if (ret != USB_RET_NODEV)
-            break;
-    }
+    if (completion) {
+        ret = ohci->usb_packet.len;
+        ohci->async_td = 0;
+        ohci->async_complete = 0;
+    } else {
+        ret = USB_RET_NODEV;
+        for (i = 0; i < ohci->num_ports; i++) {
+            dev = ohci->rhport[i].port.dev;
+            if ((ohci->rhport[i].ctrl & OHCI_PORT_PES) == 0)
+                continue;
+
+            if (ohci->async_td) {
+                /* ??? The hardware should allow one active packet per
+                   endpoint.  We only allow one active packet per controller.
+                   This should be sufficient as long as devices respond in a
+                   timely manner.
+                 */
 #ifdef DEBUG_PACKET
-    dprintf("ret=%d\n", ret);
+                dprintf("Too many pending packets\n");
 #endif
+                return 1;
+            }
+            ohci->usb_packet.pid = pid;
+            ohci->usb_packet.devaddr = OHCI_BM(ed->flags, ED_FA);
+            ohci->usb_packet.devep = OHCI_BM(ed->flags, ED_EN);
+            ohci->usb_packet.data = ohci->usb_buf;
+            ohci->usb_packet.len = len;
+            ohci->usb_packet.complete_cb = ohci_async_complete_packet;
+            ohci->usb_packet.complete_opaque = ohci;
+            ret = dev->handle_packet(dev, &ohci->usb_packet);
+            if (ret != USB_RET_NODEV)
+                break;
+        }
+#ifdef DEBUG_PACKET
+        dprintf("ret=%d\n", ret);
+#endif
+        if (ret == USB_RET_ASYNC) {
+            ohci->async_td = addr;
+            return 1;
+        }
+    }
     if (ret >= 0) {
         if (dir == OHCI_TD_DIR_IN) {
-            ohci_copy_td(&td, buf, ret, 1);
+            ohci_copy_td(&td, ohci->usb_buf, ret, 1);
 #ifdef DEBUG_PACKET
             dprintf("  data:");
             for (i = 0; i < ret; i++)
-                printf(" %.2x", buf[i]);
+                printf(" %.2x", ohci->usb_buf[i]);
             dprintf("\n");
 #endif
         } else {
@@ -608,8 +666,16 @@ static int ohci_service_ed_list(OHCIState *ohci, uint32_t head)
 
         next_ed = ed.next & OHCI_DPTR_MASK;
 
-        if ((ed.head & OHCI_ED_H) || (ed.flags & OHCI_ED_K))
+        if ((ed.head & OHCI_ED_H) || (ed.flags & OHCI_ED_K)) {
+            uint32_t addr;
+            /* Cancel pending packets for ED that have been paused.  */
+            addr = ed.head & OHCI_DPTR_MASK;
+            if (ohci->async_td && addr == ohci->async_td) {
+                usb_cancel_packet(&ohci->usb_packet);
+                ohci->async_td = 0;
+            }
             continue;
+        }
 
         /* Skip isochronous endpoints.  */
         if (ed.flags & OHCI_ED_F)
@@ -646,6 +712,26 @@ static void ohci_sof(OHCIState *ohci)
     ohci_set_interrupt(ohci, OHCI_INTR_SF);
 }
 
+/* Process Control and Bulk lists.  */
+static void ohci_process_lists(OHCIState *ohci)
+{
+    if ((ohci->ctl & OHCI_CTL_CLE) && (ohci->status & OHCI_STATUS_CLF)) {
+        if (ohci->ctrl_cur && ohci->ctrl_cur != ohci->ctrl_head)
+          dprintf("usb-ohci: head %x, cur %x\n", ohci->ctrl_head, ohci->ctrl_cur);
+        if (!ohci_service_ed_list(ohci, ohci->ctrl_head)) {
+            ohci->ctrl_cur = 0;
+            ohci->status &= ~OHCI_STATUS_CLF;
+        }
+    }
+
+    if ((ohci->ctl & OHCI_CTL_BLE) && (ohci->status & OHCI_STATUS_BLF)) {
+        if (!ohci_service_ed_list(ohci, ohci->bulk_head)) {
+            ohci->bulk_cur = 0;
+            ohci->status &= ~OHCI_STATUS_BLF;
+        }
+    }
+}
+
 /* Do frame processing on frame boundary */
 static void ohci_frame_boundary(void *opaque)
 {
@@ -661,21 +747,15 @@ static void ohci_frame_boundary(void *opaque)
         n = ohci->frame_number & 0x1f;
         ohci_service_ed_list(ohci, le32_to_cpu(hcca.intr[n]));
     }
-    if ((ohci->ctl & OHCI_CTL_CLE) && (ohci->status & OHCI_STATUS_CLF)) {
-        if (ohci->ctrl_cur && ohci->ctrl_cur != ohci->ctrl_head)
-          dprintf("usb-ohci: head %x, cur %x\n", ohci->ctrl_head, ohci->ctrl_cur);
-        if (!ohci_service_ed_list(ohci, ohci->ctrl_head)) {
-            ohci->ctrl_cur = 0;
-            ohci->status &= ~OHCI_STATUS_CLF;
-        }
-    }
 
-    if ((ohci->ctl & OHCI_CTL_BLE) && (ohci->status & OHCI_STATUS_BLF)) {
-        if (!ohci_service_ed_list(ohci, ohci->bulk_head)) {
-            ohci->bulk_cur = 0;
-            ohci->status &= ~OHCI_STATUS_BLF;
-        }
+    /* Cancel all pending packets if either of the lists has been disabled.  */
+    if (ohci->async_td &&
+        ohci->old_ctl & (~ohci->ctl) & (OHCI_CTL_BLE | OHCI_CTL_CLE)) {
+        usb_cancel_packet(&ohci->usb_packet);
+        ohci->async_td = 0;
     }
+    ohci->old_ctl = ohci->ctl;
+    ohci_process_lists(ohci);
 
     /* Frame boundary, so do EOF stuf here */
     ohci->frt = ohci->fit;
@@ -907,8 +987,7 @@ static void ohci_port_set_status(OHCIState *ohci, int portnum, uint32_t val)
 
     if (ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PRS)) {
         dprintf("usb-ohci: port %d: RESET\n", portnum);
-        port->port.dev->handle_packet(port->port.dev, USB_MSG_RESET,
-                                      0, 0, NULL, 0);
+        usb_send_msg(port->port.dev, USB_MSG_RESET);
         port->ctrl &= ~OHCI_PORT_PRS;
         /* ??? Should this also set OHCI_PORT_PESC.  */
         port->ctrl |= OHCI_PORT_PES | OHCI_PORT_PRSC;
@@ -1136,6 +1215,20 @@ static void ohci_mapfunc(PCIDevice *pci_dev, int i,
     cpu_register_physical_memory(addr, size, ohci->mem);
 }
 
+static void ohci_usb_save(QEMUFile *f, void *opaque)
+{
+    OHCIState *ohci = opaque;
+
+    pci_device_save(&ohci->pci_dev, f);
+}
+
+static int ohci_usb_load(QEMUFile *f, void *opaque, int version_id)
+{
+    OHCIState *ohci = opaque;
+
+    return pci_device_load(&ohci->pci_dev, f);
+}
+
 void usb_ohci_init(struct PCIBus *bus, int num_ports, int devfn)
 {
     OHCIState *ohci;
@@ -1186,7 +1279,8 @@ void usb_ohci_init(struct PCIBus *bus, int num_ports, int devfn)
         qemu_register_usb_port(&ohci->rhport[i].port, ohci, i, ohci_attach);
     }
 
-    register_savevm("OHCI USB", 0, 1, generic_pci_save, generic_pci_load, ohci);
+    register_savevm("OHCI USB", 0, 1, ohci_usb_save, ohci_usb_load, ohci);
 
+    ohci->async_td = 0;
     ohci_reset(ohci);
 }
index 6972d84aa71f2aa872adc5b93606b0a3f3aac993..1a59c4b97a2bba67719983499b200bcf09fbbe29 100644 (file)
@@ -82,6 +82,18 @@ typedef struct UHCIState {
     uint8_t status2; /* bit 0 and 1 are used to generate UHCI_STS_USBINT */
     QEMUTimer *frame_timer;
     UHCIPort ports[NB_PORTS];
+
+    /* Interrupts that should be raised at the end of the current frame.  */
+    uint32_t pending_int_mask;
+    /* For simplicity of implementation we only allow a single pending USB
+       request.  This means all usb traffic on this controller is effectively
+       suspended until that transfer completes.  When the transfer completes
+       the next transfer from that queue will be processed.  However 
+       other queues will not be processed until the next frame.  The solution
+       is to allow multiple pending requests.  */
+    uint32_t async_qh;
+    USBPacket usb_packet;
+    uint8_t usb_buf[2048];
 } UHCIState;
 
 typedef struct UHCI_TD {
@@ -194,8 +206,7 @@ static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
                 port = &s->ports[i];
                 dev = port->port.dev;
                 if (dev) {
-                    dev->handle_packet(dev, 
-                                       USB_MSG_RESET, 0, 0, NULL, 0);
+                    usb_send_msg(dev, USB_MSG_RESET);
                 }
             }
             uhci_reset(s);
@@ -238,8 +249,7 @@ static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
                 /* port reset */
                 if ( (val & UHCI_PORT_RESET) && 
                      !(port->ctrl & UHCI_PORT_RESET) ) {
-                    dev->handle_packet(dev, 
-                                       USB_MSG_RESET, 0, 0, NULL, 0);
+                    usb_send_msg(dev, USB_MSG_RESET);
                 }
             }
             port->ctrl = (port->ctrl & 0x01fb) | (val & ~0x01fb);
@@ -342,8 +352,7 @@ static void uhci_attach(USBPort *port1, USBDevice *dev)
             port->ctrl &= ~UHCI_PORT_LSDA;
         port->port.dev = dev;
         /* send the attach message */
-        dev->handle_packet(dev, 
-                           USB_MSG_ATTACH, 0, 0, NULL, 0);
+        usb_send_msg(dev, USB_MSG_ATTACH);
     } else {
         /* set connect status */
         if (port->ctrl & UHCI_PORT_CCS) {
@@ -358,16 +367,13 @@ static void uhci_attach(USBPort *port1, USBDevice *dev)
         dev = port->port.dev;
         if (dev) {
             /* send the detach message */
-            dev->handle_packet(dev, 
-                               USB_MSG_DETACH, 0, 0, NULL, 0);
+            usb_send_msg(dev, USB_MSG_DETACH);
         }
         port->port.dev = NULL;
     }
 }
 
-static int uhci_broadcast_packet(UHCIState *s, uint8_t pid, 
-                                 uint8_t devaddr, uint8_t devep,
-                                 uint8_t *data, int len)
+static int uhci_broadcast_packet(UHCIState *s, USBPacket *p)
 {
     UHCIPort *port;
     USBDevice *dev;
@@ -376,18 +382,18 @@ static int uhci_broadcast_packet(UHCIState *s, uint8_t pid,
 #ifdef DEBUG_PACKET
     {
         const char *pidstr;
-        switch(pid) {
+        switch(p->pid) {
         case USB_TOKEN_SETUP: pidstr = "SETUP"; break;
         case USB_TOKEN_IN: pidstr = "IN"; break;
         case USB_TOKEN_OUT: pidstr = "OUT"; break;
         default: pidstr = "?"; break;
         }
         printf("frame %d: pid=%s addr=0x%02x ep=%d len=%d\n",
-               s->frnum, pidstr, devaddr, devep, len);
-        if (pid != USB_TOKEN_IN) {
+               s->frnum, pidstr, p->devaddr, p->devep, p->len);
+        if (p->pid != USB_TOKEN_IN) {
             printf("     data_out=");
-            for(i = 0; i < len; i++) {
-                printf(" %02x", data[i]);
+            for(i = 0; i < p->len; i++) {
+                printf(" %02x", p->data[i]);
             }
             printf("\n");
         }
@@ -397,17 +403,17 @@ static int uhci_broadcast_packet(UHCIState *s, uint8_t pid,
         port = &s->ports[i];
         dev = port->port.dev;
         if (dev && (port->ctrl & UHCI_PORT_EN)) {
-            ret = dev->handle_packet(dev, pid, 
-                                     devaddr, devep,
-                                     data, len);
+            ret = dev->handle_packet(dev, p);
             if (ret != USB_RET_NODEV) {
 #ifdef DEBUG_PACKET
-                {
+                if (ret == USB_RET_ASYNC) {
+                    printf("usb-uhci: Async packet\n");
+                } else {
                     printf("     ret=%d ", ret);
-                    if (pid == USB_TOKEN_IN && ret > 0) {
+                    if (p->pid == USB_TOKEN_IN && ret > 0) {
                         printf("data_in=");
                         for(i = 0; i < ret; i++) {
-                            printf(" %02x", data[i]);
+                            printf(" %02x", p->data[i]);
                         }
                     }
                     printf("\n");
@@ -420,6 +426,8 @@ static int uhci_broadcast_packet(UHCIState *s, uint8_t pid,
     return USB_RET_NODEV;
 }
 
+static void uhci_async_complete_packet(USBPacket * packet, void *opaque);
+
 /* return -1 if fatal error (frame must be stopped)
           0 if TD successful
           1 if TD unsuccessful or inactive
@@ -427,34 +435,21 @@ static int uhci_broadcast_packet(UHCIState *s, uint8_t pid,
 static int uhci_handle_td(UHCIState *s, UHCI_TD *td, int *int_mask)
 {
     uint8_t pid;
-    uint8_t buf[2048];
     int len, max_len, err, ret;
 
-    if (!(td->ctrl & TD_CTRL_ACTIVE)){
+    if (!(td->ctrl & TD_CTRL_ACTIVE)) {
         ret = 1;
-        goto out;
+       goto out;
     }
+
     /* Clear TD's status field explicitly */
     td->ctrl = td->ctrl & (~TD_CTRL_MASK);
 
     /* TD is active */
     max_len = ((td->token >> 21) + 1) & 0x7ff;
     pid = td->token & 0xff;
-    switch(pid) {
-    case USB_TOKEN_OUT:
-    case USB_TOKEN_SETUP:
-        cpu_physical_memory_read(td->buffer, buf, max_len);
-        ret = uhci_broadcast_packet(s, pid, 
-                                    (td->token >> 8) & 0x7f,
-                                    (td->token >> 15) & 0xf,
-                                    buf, max_len);
-        len = max_len;
-        break;
-    case USB_TOKEN_IN:
-        ret = uhci_broadcast_packet(s, pid, 
-                                    (td->token >> 8) & 0x7f,
-                                    (td->token >> 15) & 0xf,
-                                    buf, max_len);
+    if (s->async_qh) {
+        ret = s->usb_packet.len;
         if (ret >= 0) {
             len = ret;
             if (len > max_len) {
@@ -463,18 +458,54 @@ static int uhci_handle_td(UHCIState *s, UHCI_TD *td, int *int_mask)
             }
             if (len > 0) {
                 /* write the data back */
-                cpu_physical_memory_write(td->buffer, buf, len);
+                cpu_physical_memory_write(td->buffer, s->usb_buf, len);
             }
         } else {
             len = 0;
         }
-        break;
-    default:
-        /* invalid pid : frame interrupted */
-        s->status |= UHCI_STS_HCPERR;
-        uhci_update_irq(s);
-        ret = -1;
-        goto out;
+        s->async_qh = 0;
+    } else {
+        s->usb_packet.pid = pid;
+        s->usb_packet.devaddr = (td->token >> 8) & 0x7f;
+        s->usb_packet.devep = (td->token >> 15) & 0xf;
+        s->usb_packet.data = s->usb_buf;
+        s->usb_packet.len = max_len;
+        s->usb_packet.complete_cb = uhci_async_complete_packet;
+        s->usb_packet.complete_opaque = s;
+        switch(pid) {
+        case USB_TOKEN_OUT:
+        case USB_TOKEN_SETUP:
+            cpu_physical_memory_read(td->buffer, s->usb_buf, max_len);
+            ret = uhci_broadcast_packet(s, &s->usb_packet);
+            len = max_len;
+            break;
+        case USB_TOKEN_IN:
+            ret = uhci_broadcast_packet(s, &s->usb_packet);
+            if (ret >= 0) {
+                len = ret;
+                if (len > max_len) {
+                    len = max_len;
+                    ret = USB_RET_BABBLE;
+                }
+                if (len > 0) {
+                    /* write the data back */
+                    cpu_physical_memory_write(td->buffer, s->usb_buf, len);
+                }
+            } else {
+                len = 0;
+            }
+            break;
+        default:
+            /* invalid pid : frame interrupted */
+            s->status |= UHCI_STS_HCPERR;
+            uhci_update_irq(s);
+            ret = -1;
+           goto out;
+        }
+    }
+    if (ret == USB_RET_ASYNC) {
+        ret = 2;
+       goto out;
     }
     if (td->ctrl & TD_CTRL_IOS)
         td->ctrl &= ~TD_CTRL_ACTIVE;
@@ -540,6 +571,61 @@ out:
     return ret;
 }
 
+static void uhci_async_complete_packet(USBPacket * packet, void *opaque)
+{
+    UHCIState *s = opaque;
+    UHCI_QH qh;
+    UHCI_TD td;
+    uint32_t link;
+    uint32_t old_td_ctrl;
+    uint32_t val;
+    int ret;
+
+    link = s->async_qh;
+    if (!link) {
+        /* This should never happen. It means a TD somehow got removed
+           without cancelling the associated async IO request.  */
+        return;
+    }
+    cpu_physical_memory_read(link & ~0xf, (uint8_t *)&qh, sizeof(qh));
+    le32_to_cpus(&qh.link);
+    le32_to_cpus(&qh.el_link);
+    /* Re-process the queue containing the async packet.  */
+    while (1) {
+        cpu_physical_memory_read(qh.el_link & ~0xf, 
+                                 (uint8_t *)&td, sizeof(td));
+        le32_to_cpus(&td.link);
+        le32_to_cpus(&td.ctrl);
+        le32_to_cpus(&td.token);
+        le32_to_cpus(&td.buffer);
+        old_td_ctrl = td.ctrl;
+        ret = uhci_handle_td(s, &td, &s->pending_int_mask);
+        /* update the status bits of the TD */
+        if (old_td_ctrl != td.ctrl) {
+            val = cpu_to_le32(td.ctrl);
+            cpu_physical_memory_write((qh.el_link & ~0xf) + 4, 
+                                      (const uint8_t *)&val, 
+                                      sizeof(val));
+        }
+        if (ret < 0)
+            break; /* interrupted frame */
+        if (ret == 2) {
+            s->async_qh = link;
+            break;
+        } else if (ret == 0) {
+            /* update qh element link */
+            qh.el_link = td.link;
+            val = cpu_to_le32(qh.el_link);
+            cpu_physical_memory_write((link & ~0xf) + 4, 
+                                      (const uint8_t *)&val, 
+                                      sizeof(val));
+            if (!(qh.el_link & 4))
+                break;
+        }
+        break;
+    }
+}
+
 static void uhci_frame_timer(void *opaque)
 {
     UHCIState *s = opaque;
@@ -548,6 +634,7 @@ static void uhci_frame_timer(void *opaque)
     int int_mask, cnt, ret;
     UHCI_TD td;
     UHCI_QH qh;
+    uint32_t old_async_qh;
 
     if (!(s->cmd & UHCI_CMD_RS)) {
         qemu_del_timer(s->frame_timer);
@@ -555,6 +642,14 @@ static void uhci_frame_timer(void *opaque)
         s->status |= UHCI_STS_HCHALTED;
         return;
     }
+    /* Complete the previous frame.  */
+    s->frnum = (s->frnum + 1) & 0x7ff;
+    if (s->pending_int_mask) {
+        s->status2 |= s->pending_int_mask;
+        s->status |= UHCI_STS_USBINT;
+        uhci_update_irq(s);
+    }
+    old_async_qh = s->async_qh;
     frame_addr = s->fl_base_addr + ((s->frnum & 0x3ff) << 2);
     cpu_physical_memory_read(frame_addr, (uint8_t *)&link, 4);
     le32_to_cpus(&link);
@@ -566,6 +661,12 @@ static void uhci_frame_timer(void *opaque)
         /* valid frame */
         if (link & 2) {
             /* QH */
+            if (link == s->async_qh) {
+                /* We've found a previously issues packet.
+                   Nothing else to do.  */
+                old_async_qh = 0;
+                break;
+            }
             cpu_physical_memory_read(link & ~0xf, (uint8_t *)&qh, sizeof(qh));
             le32_to_cpus(&qh.link);
             le32_to_cpus(&qh.el_link);
@@ -576,6 +677,10 @@ static void uhci_frame_timer(void *opaque)
             } else if (qh.el_link & 2) {
                 /* QH */
                 link = qh.el_link;
+            } else if (s->async_qh) {
+                /* We can only cope with one pending packet.  Keep looking
+                   for the previously issued packet.  */
+                link = qh.link;
             } else {
                 /* TD */
                 if (--cnt == 0)
@@ -597,7 +702,9 @@ static void uhci_frame_timer(void *opaque)
                 }
                 if (ret < 0)
                     break; /* interrupted frame */
-                if (ret == 0) {
+                if (ret == 2) {
+                    s->async_qh = link;
+                } else if (ret == 0) {
                     /* update qh element link */
                     qh.el_link = td.link;
                     val = cpu_to_le32(qh.el_link);
@@ -619,25 +726,41 @@ static void uhci_frame_timer(void *opaque)
             le32_to_cpus(&td.ctrl);
             le32_to_cpus(&td.token);
             le32_to_cpus(&td.buffer);
-            old_td_ctrl = td.ctrl;
-            ret = uhci_handle_td(s, &td, &int_mask);
-            /* update the status bits of the TD */
-            if (old_td_ctrl != td.ctrl) {
-                val = cpu_to_le32(td.ctrl);
-                cpu_physical_memory_write((link & ~0xf) + 4, 
-                                          (const uint8_t *)&val, 
-                                          sizeof(val));
+            /* Ignore isochonous transfers while there is an async packet
+               pending.  This is wrong, but we don't implement isochronous
+               transfers anyway.  */
+            if (s->async_qh == 0) {
+                old_td_ctrl = td.ctrl;
+                ret = uhci_handle_td(s, &td, &int_mask);
+                /* update the status bits of the TD */
+                if (old_td_ctrl != td.ctrl) {
+                    val = cpu_to_le32(td.ctrl);
+                    cpu_physical_memory_write((link & ~0xf) + 4, 
+                                              (const uint8_t *)&val, 
+                                              sizeof(val));
+                }
+                if (ret < 0)
+                    break; /* interrupted frame */
+                if (ret == 2) {
+                    /* We can't handle async isochronous transfers.
+                       Cancel The packet.  */
+                    fprintf(stderr, "usb-uhci: Unimplemented async packet\n");
+                    usb_cancel_packet(&s->usb_packet);
+                }
             }
-            if (ret < 0)
-                break; /* interrupted frame */
             link = td.link;
         }
     }
-    s->frnum = (s->frnum + 1) & 0x7ff;
-    if (int_mask) {
-        s->status2 |= int_mask;
-        s->status |= UHCI_STS_USBINT;
-        uhci_update_irq(s);
+    s->pending_int_mask = int_mask;
+    if (old_async_qh) {
+        /* A previously started transfer has disappeared from the transfer
+           list.  There's nothing useful we can do with it now, so just
+           discard the packet and hope it wasn't too important.  */
+#ifdef DEBUG
+        printf("Discarding USB packet\n");
+#endif
+        usb_cancel_packet(&s->usb_packet);
+        s->async_qh = 0;
     }
     /* prepare the timer for the next frame */
     expire_time = qemu_get_clock(vm_clock) + 
@@ -663,6 +786,8 @@ void uhci_usb_save(QEMUFile *f, void *opaque)
     int i;
     UHCIState *s = (UHCIState*)opaque;
 
+    pci_device_save(&s->dev, f);
+
     qemu_put_be16s(f, &s->cmd);
     qemu_put_be16s(f, &s->status);
     qemu_put_be16s(f, &s->intr);
@@ -686,6 +811,10 @@ int uhci_usb_load(QEMUFile *f, void *opaque, int version_id)
     if (version_id != 1)
         return -EINVAL;
 
+    i = pci_device_load(&s->dev, f);
+    if (i < 0)
+       return i;
+
     qemu_get_be16s(f, &s->cmd);
     qemu_get_be16s(f, &s->status);
     qemu_get_be16s(f, &s->intr);
@@ -739,7 +868,5 @@ void usb_uhci_init(PCIBus *bus, int devfn)
     pci_register_io_region(&s->dev, 4, 0x20, 
                            PCI_ADDRESS_SPACE_IO, uhci_map);
 
-    register_savevm("UHCI_usb_pci", 0, 1, generic_pci_save, generic_pci_load, s);
-
     register_savevm("UHCI usb controller", 0, 1, uhci_usb_save, uhci_usb_load, s);
 }
index e4166518b0c5984f50945ee4a513510d3245dabd..4400ee6c345862e9b71d4512d0d0fe1cbe1d5b75 100644 (file)
@@ -38,13 +38,13 @@ void usb_attach(USBPort *port, USBDevice *dev)
 #define SETUP_STATE_DATA 1
 #define SETUP_STATE_ACK  2
 
-int usb_generic_handle_packet(USBDevice *s, int pid, 
-                              uint8_t devaddr, uint8_t devep,
-                              uint8_t *data, int len)
+int usb_generic_handle_packet(USBDevice *s, USBPacket *p)
 {
     int l, ret = 0;
+    int len = p->len;
+    uint8_t *data = p->data;
 
-    switch(pid) {
+    switch(p->pid) {
     case USB_MSG_ATTACH:
         s->state = USB_STATE_ATTACHED;
         break;
@@ -58,7 +58,7 @@ int usb_generic_handle_packet(USBDevice *s, int pid,
         s->handle_reset(s);
         break;
     case USB_TOKEN_SETUP:
-        if (s->state < USB_STATE_DEFAULT || devaddr != s->addr)
+        if (s->state < USB_STATE_DEFAULT || p->devaddr != s->addr)
             return USB_RET_NODEV;
         if (len != 8)
             goto fail;
@@ -85,9 +85,9 @@ int usb_generic_handle_packet(USBDevice *s, int pid,
         }
         break;
     case USB_TOKEN_IN:
-        if (s->state < USB_STATE_DEFAULT || devaddr != s->addr)
+        if (s->state < USB_STATE_DEFAULT || p->devaddr != s->addr)
             return USB_RET_NODEV;
-        switch(devep) {
+        switch(p->devep) {
         case 0:
             switch(s->setup_state) {
             case SETUP_STATE_ACK:
@@ -125,14 +125,14 @@ int usb_generic_handle_packet(USBDevice *s, int pid,
             }
             break;
         default:
-            ret = s->handle_data(s, pid, devep, data, len);
+            ret = s->handle_data(s, p);
             break;
         }
         break;
     case USB_TOKEN_OUT:
-        if (s->state < USB_STATE_DEFAULT || devaddr != s->addr)
+        if (s->state < USB_STATE_DEFAULT || p->devaddr != s->addr)
             return USB_RET_NODEV;
-        switch(devep) {
+        switch(p->devep) {
         case 0:
             switch(s->setup_state) {
             case SETUP_STATE_ACK:
@@ -163,7 +163,7 @@ int usb_generic_handle_packet(USBDevice *s, int pid,
             }
             break;
         default:
-            ret = s->handle_data(s, pid, devep, data, len);
+            ret = s->handle_data(s, p);
             break;
         }
         break;
@@ -192,6 +192,15 @@ int set_usb_string(uint8_t *buf, const char *str)
     return q - buf;
 }
 
+/* Send an internal message to a USB device.  */
+void usb_send_msg(USBDevice *dev, int msg)
+{
+    USBPacket p;
+    memset(&p, 0, sizeof(p));
+    p.pid = msg;
+    dev->handle_packet(dev, &p);
+}
+
 void generic_usb_save(QEMUFile* f, void *opaque)
 {
     USBDevice *s = (USBDevice*)opaque;
index 9df69f8dc8c412be8f88f9660400d1bcaa6594d9..48967516ec37e712f5e18f3c1fdf373410ca4a4b 100644 (file)
@@ -34,6 +34,7 @@
 #define USB_RET_NAK    (-2)
 #define USB_RET_STALL  (-3)
 #define USB_RET_BABBLE (-4)
+#define USB_RET_ASYNC  (-5)
 
 #define USB_SPEED_LOW   0
 #define USB_SPEED_FULL  1
 
 typedef struct USBPort USBPort;
 typedef struct USBDevice USBDevice;
+typedef struct USBPacket USBPacket;
 
 /* definition of a USB device */
 struct USBDevice {
     void *opaque;
-    int (*handle_packet)(USBDevice *dev, int pid, 
-                         uint8_t devaddr, uint8_t devep,
-                         uint8_t *data, int len);
+    int (*handle_packet)(USBDevice *dev, USBPacket *p);
     void (*handle_destroy)(USBDevice *dev);
 
     int speed;
@@ -126,8 +126,7 @@ struct USBDevice {
     void (*handle_reset)(USBDevice *dev);
     int (*handle_control)(USBDevice *dev, int request, int value,
                           int index, int length, uint8_t *data);
-    int (*handle_data)(USBDevice *dev, int pid, uint8_t devep,
-                       uint8_t *data, int len);
+    int (*handle_data)(USBDevice *dev, USBPacket *p);
     uint8_t addr;
     char devname[32];
     
@@ -151,11 +150,54 @@ struct USBPort {
     struct USBPort *next; /* Used internally by qemu.  */
 };
 
+typedef void USBCallback(USBPacket * packet, void *opaque);
+
+/* Structure used to hold information about an active USB packet.  */
+struct USBPacket {
+    /* Data fields for use by the driver.  */
+    int pid;
+    uint8_t devaddr;
+    uint8_t devep;
+    uint8_t *data;
+    int len;
+    /* Internal use by the USB layer.  */
+    USBCallback *complete_cb;
+    void *complete_opaque;
+    USBCallback *cancel_cb;
+    void * *cancel_opaque;
+};
+
+/* Defer completion of a USB packet.  The hadle_packet routine should then
+   return USB_RET_ASYNC.  Packets that complete immediately (before
+   handle_packet returns) should not call this method.  */
+static inline void usb_defer_packet(USBPacket *p, USBCallback *cancel,
+                                    void * opaque)
+{
+    p->cancel_cb = cancel;
+    p->cancel_opaque = opaque;
+}
+
+/* Notify the controller that an async packet is complete.  This should only
+   be called for packets previously deferred with usb_defer_packet, and
+   should never be called from within handle_packet.  */
+static inline void usb_packet_complete(USBPacket *p)
+{
+    p->complete_cb(p, p->complete_opaque);
+}
+
+/* Cancel an active packet.  The packed must have been deferred with
+   usb_defer_packet,  and not yet completed.  */
+static inline void usb_cancel_packet(USBPacket * p)
+{
+    p->cancel_cb(p, p->cancel_opaque);
+}
+
 void usb_attach(USBPort *port, USBDevice *dev);
-int usb_generic_handle_packet(USBDevice *s, int pid, 
-                              uint8_t devaddr, uint8_t devep,
-                              uint8_t *data, int len);
+int usb_generic_handle_packet(USBDevice *s, USBPacket *p);
 int set_usb_string(uint8_t *buf, const char *str);
+void usb_send_msg(USBDevice *dev, int msg);
+
+void usb_packet_complete(USBPacket *p);
 
 /* usb hub */
 USBDevice *usb_hub_init(int nb_ports);
index 34a4bc6c5a735522453d30713cc2f3025cc3e428..32854c2f9414f8eec214c870c8e0421d772645f3 100644 (file)
@@ -11,7 +11,7 @@
 
 static inline uint32_t vpb_pci_config_addr(target_phys_addr_t addr)
 {
-    return addr & 0xf8ff;
+    return addr & 0xffffff;
 }
 
 static void pci_vpb_config_writeb (void *opaque, target_phys_addr_t addr,
@@ -77,31 +77,54 @@ static CPUReadMemoryFunc *pci_vpb_config_read[] = {
     &pci_vpb_config_readl,
 };
 
-static void pci_vpb_set_irq(PCIDevice *d, void *pic, int irq_num, int level)
+static int pci_vpb_irq;
+
+static int pci_vpb_map_irq(PCIDevice *d, int irq_num)
+{
+    return irq_num;
+}
+
+static void pci_vpb_set_irq(void *pic, int irq_num, int level)
 {
-    pic_set_irq_new(pic, 27 + irq_num, level);
+    pic_set_irq_new(pic, pci_vpb_irq + irq_num, level);
 }
 
-PCIBus *pci_vpb_init(void *pic)
+PCIBus *pci_vpb_init(void *pic, int irq, int realview)
 {
     PCIBus *s;
     PCIDevice *d;
     int mem_config;
-
-    s = pci_register_bus(pci_vpb_set_irq, pic, 11 << 3);
+    uint32_t base;
+    const char * name;
+
+    pci_vpb_irq = irq;
+    if (realview) {
+        base = 0x60000000;
+        name = "RealView EB PCI Controller";
+    } else {
+        base = 0x40000000;
+        name = "Versatile/PB PCI Controller";
+    }
+    s = pci_register_bus(pci_vpb_set_irq, pci_vpb_map_irq, pic, 11 << 3, 4);
     /* ??? Register memory space.  */
 
     mem_config = cpu_register_io_memory(0, pci_vpb_config_read,
                                         pci_vpb_config_write, s);
     /* Selfconfig area.  */
-    cpu_register_physical_memory(0x41000000, 0x10000, mem_config);
+    cpu_register_physical_memory(base + 0x01000000, 0x1000000, mem_config);
     /* Normal config area.  */
-    cpu_register_physical_memory(0x42000000, 0x10000, mem_config);
+    cpu_register_physical_memory(base + 0x02000000, 0x1000000, mem_config);
+
+    d = pci_register_device(s, name, sizeof(PCIDevice), -1, NULL, NULL);
+
+    if (realview) {
+        /* IO memory area.  */
+        isa_mmio_init(base + 0x03000000, 0x00100000);
+    }
 
-    d = pci_register_device(s, "Versatile/PB PCI Controller",
-                            sizeof(PCIDevice), -1, NULL, NULL);
     d->config[0x00] = 0xee; // vendor_id
     d->config[0x01] = 0x10;
+    /* Both boards have the same device ID.  Oh well.  */
     d->config[0x02] = 0x00; // device_id
     d->config[0x03] = 0x03;
     d->config[0x04] = 0x00;
index 28ec1374baa821eb75026f875c69728871466fea..bc42472ade3bc3674040a8617cf023d6371b031a 100644 (file)
@@ -10,8 +10,6 @@
 #include "vl.h"
 #include "arm_pic.h"
 
-#define LOCK_VALUE 0xa05f
-
 /* Primary interrupt controller.  */
 
 typedef struct vpb_sic_state
@@ -75,7 +73,7 @@ static uint32_t vpb_sic_read(void *opaque, target_phys_addr_t offset)
     case 8: /* PICENABLE */
         return s->pic_enable;
     default:
-        printf ("vpb_sic_read: Bad register offset 0x%x\n", offset);
+        printf ("vpb_sic_read: Bad register offset 0x%x\n", (int)offset);
         return 0;
     }
 }
@@ -110,7 +108,7 @@ static void vpb_sic_write(void *opaque, target_phys_addr_t offset,
         vpb_sic_update_pic(s);
         break;
     default:
-        printf ("vpb_sic_write: Bad register offset 0x%x\n", offset);
+        printf ("vpb_sic_write: Bad register offset 0x%x\n", (int)offset);
         return;
     }
     vpb_sic_update(s);
@@ -147,188 +145,6 @@ static vpb_sic_state *vpb_sic_init(uint32_t base, void *parent, int irq)
     return s;
 }
 
-/* System controller.  */
-
-typedef struct {
-    uint32_t base;
-    uint32_t leds;
-    uint16_t lockval;
-    uint32_t cfgdata1;
-    uint32_t cfgdata2;
-    uint32_t flags;
-    uint32_t nvflags;
-    uint32_t resetlevel;
-} vpb_sys_state;
-
-static uint32_t vpb_sys_read(void *opaque, target_phys_addr_t offset)
-{
-    vpb_sys_state *s = (vpb_sys_state *)opaque;
-
-    offset -= s->base;
-    switch (offset) {
-    case 0x00: /* ID */
-        return 0x41007004;
-    case 0x04: /* SW */
-        /* General purpose hardware switches.
-           We don't have a useful way of exposing these to the user.  */
-        return 0;
-    case 0x08: /* LED */
-        return s->leds;
-    case 0x20: /* LOCK */
-        return s->lockval;
-    case 0x0c: /* OSC0 */
-    case 0x10: /* OSC1 */
-    case 0x14: /* OSC2 */
-    case 0x18: /* OSC3 */
-    case 0x1c: /* OSC4 */
-    case 0x24: /* 100HZ */
-        /* ??? Implement these.  */
-        return 0;
-    case 0x28: /* CFGDATA1 */
-        return s->cfgdata1;
-    case 0x2c: /* CFGDATA2 */
-        return s->cfgdata2;
-    case 0x30: /* FLAGS */
-        return s->flags;
-    case 0x38: /* NVFLAGS */
-        return s->nvflags;
-    case 0x40: /* RESETCTL */
-        return s->resetlevel;
-    case 0x44: /* PCICTL */
-        return 1;
-    case 0x48: /* MCI */
-        return 0;
-    case 0x4c: /* FLASH */
-        return 0;
-    case 0x50: /* CLCD */
-        return 0x1000;
-    case 0x54: /* CLCDSER */
-        return 0;
-    case 0x58: /* BOOTCS */
-        return 0;
-    case 0x5c: /* 24MHz */
-        /* ??? not implemented.  */
-        return 0;
-    case 0x60: /* MISC */
-        return 0;
-    case 0x64: /* DMAPSR0 */
-    case 0x68: /* DMAPSR1 */
-    case 0x6c: /* DMAPSR2 */
-    case 0x8c: /* OSCRESET0 */
-    case 0x90: /* OSCRESET1 */
-    case 0x94: /* OSCRESET2 */
-    case 0x98: /* OSCRESET3 */
-    case 0x9c: /* OSCRESET4 */
-    case 0xc0: /* SYS_TEST_OSC0 */
-    case 0xc4: /* SYS_TEST_OSC1 */
-    case 0xc8: /* SYS_TEST_OSC2 */
-    case 0xcc: /* SYS_TEST_OSC3 */
-    case 0xd0: /* SYS_TEST_OSC4 */
-        return 0;
-    default:
-        printf ("vpb_sys_read: Bad register offset 0x%x\n", offset);
-        return 0;
-    }
-}
-
-static void vpb_sys_write(void *opaque, target_phys_addr_t offset,
-                          uint32_t val)
-{
-    vpb_sys_state *s = (vpb_sys_state *)opaque;
-    offset -= s->base;
-
-    switch (offset) {
-    case 0x08: /* LED */
-        s->leds = val;
-    case 0x0c: /* OSC0 */
-    case 0x10: /* OSC1 */
-    case 0x14: /* OSC2 */
-    case 0x18: /* OSC3 */
-    case 0x1c: /* OSC4 */
-        /* ??? */
-        break;
-    case 0x20: /* LOCK */
-        if (val == LOCK_VALUE)
-            s->lockval = val;
-        else
-            s->lockval = val & 0x7fff;
-        break;
-    case 0x28: /* CFGDATA1 */
-        /* ??? Need to implement this.  */
-        s->cfgdata1 = val;
-        break;
-    case 0x2c: /* CFGDATA2 */
-        /* ??? Need to implement this.  */
-        s->cfgdata2 = val;
-        break;
-    case 0x30: /* FLAGSSET */
-        s->flags |= val;
-        break;
-    case 0x34: /* FLAGSCLR */
-        s->flags &= ~val;
-        break;
-    case 0x38: /* NVFLAGSSET */
-        s->nvflags |= val;
-        break;
-    case 0x3c: /* NVFLAGSCLR */
-        s->nvflags &= ~val;
-        break;
-    case 0x40: /* RESETCTL */
-        if (s->lockval == LOCK_VALUE) {
-            s->resetlevel = val;
-            if (val & 0x100)
-                cpu_abort(cpu_single_env, "Board reset\n");
-        }
-        break;
-    case 0x44: /* PCICTL */
-        /* nothing to do.  */
-        break;
-    case 0x4c: /* FLASH */
-    case 0x50: /* CLCD */
-    case 0x54: /* CLCDSER */
-    case 0x64: /* DMAPSR0 */
-    case 0x68: /* DMAPSR1 */
-    case 0x6c: /* DMAPSR2 */
-    case 0x8c: /* OSCRESET0 */
-    case 0x90: /* OSCRESET1 */
-    case 0x94: /* OSCRESET2 */
-    case 0x98: /* OSCRESET3 */
-    case 0x9c: /* OSCRESET4 */
-        break;
-    default:
-        printf ("vpb_sys_write: Bad register offset 0x%x\n", offset);
-        return;
-    }
-}
-
-static CPUReadMemoryFunc *vpb_sys_readfn[] = {
-   vpb_sys_read,
-   vpb_sys_read,
-   vpb_sys_read
-};
-
-static CPUWriteMemoryFunc *vpb_sys_writefn[] = {
-   vpb_sys_write,
-   vpb_sys_write,
-   vpb_sys_write
-};
-
-static vpb_sys_state *vpb_sys_init(uint32_t base)
-{
-    vpb_sys_state *s;
-    int iomemtype;
-
-    s = (vpb_sys_state *)qemu_mallocz(sizeof(vpb_sys_state));
-    if (!s)
-        return NULL;
-    s->base = base;
-    iomemtype = cpu_register_io_memory(0, vpb_sys_readfn,
-                                       vpb_sys_writefn, s);
-    cpu_register_physical_memory(base, 0x00000fff, iomemtype);
-    /* ??? Save/restore.  */
-    return s;
-}
-
 /* Board init.  */
 
 /* The AB and PB boards both use the same core, just with different
@@ -355,14 +171,14 @@ static void versatile_init(int ram_size, int vga_ram_size, int boot_device,
     /* SDRAM at address zero.  */
     cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
 
-    vpb_sys_init(0x10000000);
+    arm_sysctl_init(0x10000000, 0x41007004);
     pic = arm_pic_init_cpu(env);
     pic = pl190_init(0x10140000, pic, ARM_PIC_CPU_IRQ, ARM_PIC_CPU_FIQ);
     sic = vpb_sic_init(0x10003000, pic, 31);
     pl050_init(0x10006000, sic, 3, 0);
     pl050_init(0x10007000, sic, 4, 1);
 
-    pci_bus = pci_vpb_init(sic);
+    pci_bus = pci_vpb_init(sic, 27, 0);
     /* The Versatile PCI bridge does not provide access to PCI IO space,
        so many of the qemu PCI devices are not useable.  */
     for(n = 0; n < nb_nics; n++) {
@@ -372,7 +188,7 @@ static void versatile_init(int ram_size, int vga_ram_size, int boot_device,
         if (strcmp(nd->model, "smc91c111") == 0) {
             smc91c111_init(nd, 0x10010000, sic, 25);
         } else {
-            pci_nic_init(pci_bus, nd);
+            pci_nic_init(pci_bus, nd, -1);
         }
     }
     if (usb_enabled) {
@@ -390,7 +206,7 @@ static void versatile_init(int ram_size, int vga_ram_size, int boot_device,
     pl011_init(0x101f3000, pic, 14, serial_hds[2]);
     pl011_init(0x10009000, sic, 6, serial_hds[3]);
 
-    pl080_init(0x10130000, pic, 17);
+    pl080_init(0x10130000, pic, 17, 8);
     sp804_init(0x101e2000, pic, 4);
     sp804_init(0x101e3000, pic, 5);
 
@@ -434,7 +250,7 @@ static void versatile_init(int ram_size, int vga_ram_size, int boot_device,
     /*  0x101f3000 UART2.  */
     /* 0x101f4000 SSPI.  */
 
-    arm_load_kernel(ram_size, kernel_filename, kernel_cmdline,
+    arm_load_kernel(env, ram_size, kernel_filename, kernel_cmdline,
                     initrd_filename, board_id);
 }
 
index a8402aa75fdc6901a41f6a3bc1a2690c3a2a21da..cb34f289fb556ae9ee353676841699f04bd524b1 100644 (file)
@@ -143,9 +143,6 @@ static uint32_t expand4[256];
 static uint16_t expand2[256];
 static uint8_t expand4to8[16];
 
-VGAState *vga_state;
-int vga_io_memory;
-
 static void vga_screen_dump(void *opaque, const char *filename);
 
 static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
@@ -425,7 +422,9 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
         case VBE_DISPI_INDEX_ID:
             if (val == VBE_DISPI_ID0 ||
                 val == VBE_DISPI_ID1 ||
-                val == VBE_DISPI_ID2) {
+                val == VBE_DISPI_ID2 ||
+                val == VBE_DISPI_ID3 ||
+                val == VBE_DISPI_ID4) {
                 s->vbe_regs[s->vbe_index] = val;
             }
             break;
@@ -448,7 +447,11 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
             }
             break;
         case VBE_DISPI_INDEX_BANK:
-            val &= s->vbe_bank_mask;
+            if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
+              val &= (s->vbe_bank_mask >> 2);
+            } else {
+              val &= s->vbe_bank_mask;
+            }
             s->vbe_regs[s->vbe_index] = val;
             s->bank_offset = (val << 16);
             break;
@@ -508,6 +511,7 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
                 /* XXX: the bios should do that */
                 s->bank_offset = 0;
             }
+            s->dac_8bit = (val & VBE_DISPI_8BIT_DAC) > 0;
             s->vbe_regs[s->vbe_index] = val;
             break;
         case VBE_DISPI_INDEX_VIRT_WIDTH:
@@ -924,9 +928,15 @@ static int update_palette256(VGAState *s)
     palette = s->last_palette;
     v = 0;
     for(i = 0; i < 256; i++) {
-        col = s->rgb_to_pixel(c6_to_8(s->palette[v]), 
-                              c6_to_8(s->palette[v + 1]), 
-                              c6_to_8(s->palette[v + 2]));
+        if (s->dac_8bit) {
+          col = s->rgb_to_pixel(s->palette[v], 
+                                s->palette[v + 1], 
+                                s->palette[v + 2]);
+        } else {
+          col = s->rgb_to_pixel(c6_to_8(s->palette[v]), 
+                                c6_to_8(s->palette[v + 1]), 
+                                c6_to_8(s->palette[v + 2]));
+        }
         if (col != palette[i]) {
             full_update = 1;
             palette[i] = col;
@@ -938,13 +948,15 @@ static int update_palette256(VGAState *s)
 
 static void vga_get_offsets(VGAState *s, 
                             uint32_t *pline_offset, 
-                            uint32_t *pstart_addr)
+                            uint32_t *pstart_addr,
+                            uint32_t *pline_compare)
 {
-    uint32_t start_addr, line_offset;
+    uint32_t start_addr, line_offset, line_compare;
 #ifdef CONFIG_BOCHS_VBE
     if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
         line_offset = s->vbe_line_offset;
         start_addr = s->vbe_start_addr;
+        line_compare = 65535;
     } else
 #endif
     {  
@@ -954,9 +966,15 @@ static void vga_get_offsets(VGAState *s,
 
         /* starting address */
         start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
+
+        /* line compare */
+        line_compare = s->cr[0x18] | 
+            ((s->cr[0x07] & 0x10) << 4) |
+            ((s->cr[0x09] & 0x40) << 3);
     }
     *pline_offset = line_offset;
     *pstart_addr = start_addr;
+    *pline_compare = line_compare;
 }
 
 /* update start_addr and line_offset. Return TRUE if modified */
@@ -967,11 +985,7 @@ static int update_basic_params(VGAState *s)
     
     full_update = 0;
 
-    s->get_offsets(s, &line_offset, &start_addr);
-    /* line compare */
-    line_compare = s->cr[0x18] | 
-        ((s->cr[0x07] & 0x10) << 4) |
-        ((s->cr[0x09] & 0x40) << 3);
+    s->get_offsets(s, &line_offset, &start_addr, &line_compare);
 
     if (line_offset != s->line_offset ||
         start_addr != s->start_addr ||
@@ -1732,6 +1746,9 @@ static void vga_save(QEMUFile *f, void *opaque)
     int i;
 #endif
 
+    if (s->pci_dev)
+        pci_device_save(s->pci_dev, f);
+
     qemu_put_be32s(f, &s->latch);
     qemu_put_8s(f, &s->sr_index);
     qemu_put_buffer(f, s->sr, 8);
@@ -1771,14 +1788,20 @@ static void vga_save(QEMUFile *f, void *opaque)
 static int vga_load(QEMUFile *f, void *opaque, int version_id)
 {
     VGAState *s = opaque;
-    int is_vbe;
+    int is_vbe, ret;
 #ifdef CONFIG_BOCHS_VBE
     int i;
 #endif
 
-    if (version_id != 1)
+    if (version_id > 2)
         return -EINVAL;
 
+    if (s->pci_dev && version_id >= 2) {
+        ret = pci_device_load(s->pci_dev, f);
+        if (ret < 0)
+            return ret;
+    }
+
     qemu_get_be32s(f, &s->latch);
     qemu_get_8s(f, &s->sr_index);
     qemu_get_buffer(f, s->sr, 8);
@@ -1822,10 +1845,16 @@ static int vga_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
+typedef struct PCIVGAState {
+    PCIDevice dev;
+    VGAState vga_state;
+} PCIVGAState;
+
 static void vga_map(PCIDevice *pci_dev, int region_num, 
                     uint32_t addr, uint32_t size, int type)
 {
-    VGAState *s = vga_state;
+    PCIVGAState *d = (PCIVGAState *)pci_dev;
+    VGAState *s = &d->vga_state;
     if (region_num == PCI_ROM_SLOT) {
         cpu_register_physical_memory(addr, s->bios_size, s->bios_offset);
     } else {
@@ -2014,26 +2043,16 @@ void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base,
     s->get_resolution = vga_get_resolution;
     graphic_console_init(s->ds, vga_update_display, vga_invalidate_display,
                          vga_screen_dump, s);
-    /* XXX: currently needed for display */
-    vga_state = s;
 
     vga_bios_init(s);
 }
 
-
-int vga_initialize(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, 
-                   unsigned long vga_ram_offset, int vga_ram_size,
-                   unsigned long vga_bios_offset, int vga_bios_size)
+/* used by both ISA and PCI */
+static void vga_init(VGAState *s)
 {
-    VGAState *s;
-
-    s = qemu_mallocz(sizeof(VGAState));
-    if (!s)
-        return -1;
-
-    vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
+    int vga_io_memory;
 
-    register_savevm("vga", 0, 1, vga_save, vga_load, s);
+    register_savevm("vga", 0, 2, vga_save, vga_load, s);
 
     register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
 
@@ -2078,43 +2097,69 @@ int vga_initialize(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
     vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
     cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000, 
                                  vga_io_memory);
+}
+
+int isa_vga_init(DisplayState *ds, uint8_t *vga_ram_base, 
+                 unsigned long vga_ram_offset, int vga_ram_size)
+{
+    VGAState *s;
+
+    s = qemu_mallocz(sizeof(VGAState));
+    if (!s)
+        return -1;
+
+    vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
+    vga_init(s);
 
-    if (bus) {
-        PCIDevice *d;
-        uint8_t *pci_conf;
-
-        d = pci_register_device(bus, "VGA", 
-                                sizeof(PCIDevice),
-                                -1, NULL, NULL);
-        pci_conf = d->config;
-        pci_conf[0x00] = 0x34; // dummy VGA (same as Bochs ID)
-        pci_conf[0x01] = 0x12;
-        pci_conf[0x02] = 0x11;
-        pci_conf[0x03] = 0x11;
-        pci_conf[0x0a] = 0x00; // VGA controller 
-        pci_conf[0x0b] = 0x03;
-        pci_conf[0x0e] = 0x00; // header_type
-
-        /* XXX: vga_ram_size must be a power of two */
-        pci_register_io_region(d, 0, vga_ram_size, 
-                               PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
-        if (vga_bios_size != 0) {
-            unsigned int bios_total_size;
-            s->bios_offset = vga_bios_offset;
-            s->bios_size = vga_bios_size;
-            /* must be a power of two */
-            bios_total_size = 1;
-            while (bios_total_size < vga_bios_size)
-                bios_total_size <<= 1;
-            pci_register_io_region(d, PCI_ROM_SLOT, bios_total_size, 
-                                   PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
-        }
-    } else {
 #ifdef CONFIG_BOCHS_VBE
-        /* XXX: use optimized standard vga accesses */
-        cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS, 
-                                     vga_ram_size, vga_ram_offset);
+    /* XXX: use optimized standard vga accesses */
+    cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS, 
+                                 vga_ram_size, vga_ram_offset);
 #endif
+    return 0;
+}
+
+int pci_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, 
+                 unsigned long vga_ram_offset, int vga_ram_size,
+                 unsigned long vga_bios_offset, int vga_bios_size)
+{
+    PCIVGAState *d;
+    VGAState *s;
+    uint8_t *pci_conf;
+    
+    d = (PCIVGAState *)pci_register_device(bus, "VGA", 
+                                           sizeof(PCIVGAState),
+                                           -1, NULL, NULL);
+    if (!d)
+        return -1;
+    s = &d->vga_state;
+    
+    vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
+    vga_init(s);
+    s->pci_dev = &d->dev;
+    
+    pci_conf = d->dev.config;
+    pci_conf[0x00] = 0x34; // dummy VGA (same as Bochs ID)
+    pci_conf[0x01] = 0x12;
+    pci_conf[0x02] = 0x11;
+    pci_conf[0x03] = 0x11;
+    pci_conf[0x0a] = 0x00; // VGA controller 
+    pci_conf[0x0b] = 0x03;
+    pci_conf[0x0e] = 0x00; // header_type
+    
+    /* XXX: vga_ram_size must be a power of two */
+    pci_register_io_region(&d->dev, 0, vga_ram_size, 
+                           PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
+    if (vga_bios_size != 0) {
+        unsigned int bios_total_size;
+        s->bios_offset = vga_bios_offset;
+        s->bios_size = vga_bios_size;
+        /* must be a power of two */
+        bios_total_size = 1;
+        while (bios_total_size < vga_bios_size)
+            bios_total_size <<= 1;
+        pci_register_io_region(&d->dev, PCI_ROM_SLOT, bios_total_size, 
+                               PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
     }
     return 0;
 }
index f5a98a8904e10ee206b4454dd85af37dd7556c80..3dd9330573d055003b43a709ab25a60a1477f59a 100644 (file)
@@ -49,6 +49,8 @@
 #define VBE_DISPI_ID0                   0xB0C0
 #define VBE_DISPI_ID1                   0xB0C1
 #define VBE_DISPI_ID2                   0xB0C2
+#define VBE_DISPI_ID3                   0xB0C3
+#define VBE_DISPI_ID4                   0xB0C4
   
 #define VBE_DISPI_DISABLED              0x00
 #define VBE_DISPI_ENABLED               0x01
@@ -85,6 +87,7 @@
     unsigned int vram_size;                                             \
     unsigned long bios_offset;                                          \
     unsigned int bios_size;                                             \
+    PCIDevice *pci_dev;                                                 \
     uint32_t latch;                                                     \
     uint8_t sr_index;                                                   \
     uint8_t sr[256];                                                    \
     uint8_t dac_read_index;                                             \
     uint8_t dac_write_index;                                            \
     uint8_t dac_cache[3]; /* used when writing */                       \
+    int dac_8bit;                                                       \
     uint8_t palette[768];                                               \
     int32_t bank_offset;                                                \
     int (*get_bpp)(struct VGAState *s);                                 \
     void (*get_offsets)(struct VGAState *s,                             \
                         uint32_t *pline_offset,                         \
-                        uint32_t *pstart_addr);                         \
+                        uint32_t *pstart_addr,                          \
+                        uint32_t *pline_compare);                       \
     void (*get_resolution)(struct VGAState *s,                          \
                         int *pwidth,                                    \
                         int *pheight);                                  \
index 47dd03b43ded45f915f63ea4f24ff12dde891bf5..50700f2ea25d8cb6aead24ff5fbe1de1b00306e1 100644 (file)
@@ -97,6 +97,23 @@ struct pci_config_header {
     uint8_t  max_lat;
 };
 
+void xen_pci_save(QEMUFile *f, void *opaque)
+{
+    PCIDevice *d = opaque;
+
+    pci_device_save(d, f);
+}
+
+int xen_pci_load(QEMUFile *f, void *opaque, int version_id)
+{
+    PCIDevice *d = opaque;
+
+    if (version_id != 1)
+        return -EINVAL;
+
+    return pci_device_load(d, f);
+}
+
 void pci_xen_platform_init(PCIBus *bus)
 {
     PCIDevice *d;
@@ -128,6 +145,6 @@ void pci_xen_platform_init(PCIBus *bus)
     pci_register_io_region(d, 1, 0x1000000, PCI_ADDRESS_SPACE_MEM_PREFETCH,
                           platform_mmio_map);
 
-    register_savevm("platform", 0, 1, generic_pci_save, generic_pci_load, d);
+    register_savevm("platform", 0, 1, xen_pci_save, xen_pci_load, d);
     printf("Done register platform.\n");
 }
index b86ab2a0b06b1bd077f108b7313a2c34ff561749..bd893288aa0cc5e6936aaa7e5b09ff6d48a78b81 100644 (file)
@@ -36,10 +36,8 @@ static int get_keysym(const char *name)
 #define MAX_EXTRA_COUNT 256
 typedef struct {
     uint16_t keysym2keycode[MAX_NORMAL_KEYCODE];
-    int keysym2numlock[MAX_NORMAL_KEYCODE];
     struct {
        int keysym;
-       int numlock;
        uint16_t keycode;
     } keysym2keycode_extra[MAX_EXTRA_COUNT];
     int extra_count;
@@ -52,8 +50,6 @@ static kbd_layout_t *parse_keyboard_layout(const char *language,
     char file_name[1024];
     char line[1024];
     int len;
-    int *keycode2numlock;
-    int i;
 
     snprintf(file_name, sizeof(file_name),
              "%s/keymaps/%s", bios_dir, language);
@@ -67,15 +63,6 @@ static kbd_layout_t *parse_keyboard_layout(const char *language,
                "Could not read keymap file: '%s'\n", file_name);
        return 0;
     }
-
-    /* Allocate a temporary map tracking which keycodes change when numlock is
-       set.  Keycodes are 16 bit, so 65536 is safe. */
-    keycode2numlock = malloc(65536 * sizeof(int));
-    if (!keycode2numlock) {
-        perror("Could not read keymap file");
-       return 0;
-    }
-
     for(;;) {
        if (fgets(line, 1024, f) == NULL)
             break;
@@ -99,19 +86,13 @@ static kbd_layout_t *parse_keyboard_layout(const char *language,
                if (keysym == 0) {
                     //             fprintf(stderr, "Warning: unknown keysym %s\n", line);
                } else {
-                   char *rest = end_of_keysym + 1;
-                   int keycode = strtol(rest, &rest, 0);
-                   int numlock = (rest != NULL &&
-                                  strstr(rest, "numlock") != NULL);
-
-                    keycode2numlock[keycode] = numlock;
-
+                   const char *rest = end_of_keysym + 1;
+                   int keycode = strtol(rest, NULL, 0);
                    /* if(keycode&0x80)
                       keycode=(keycode<<8)^0x80e0; */
                    if (keysym < MAX_NORMAL_KEYCODE) {
                        //fprintf(stderr,"Setting keysym %s (%d) to %d\n",line,keysym,keycode);
                        k->keysym2keycode[keysym] = keycode;
-                       k->keysym2numlock[keysym] = numlock;
                    } else {
                        if (k->extra_count >= MAX_EXTRA_COUNT) {
                            fprintf(stderr,
@@ -126,8 +107,6 @@ static kbd_layout_t *parse_keyboard_layout(const char *language,
                                keysym = keysym;
                            k->keysym2keycode_extra[k->extra_count].
                                keycode = keycode;
-                           k->keysym2keycode_extra[k->extra_count].
-                               numlock = numlock;
                            k->extra_count++;
                        }
                    }
@@ -136,22 +115,6 @@ static kbd_layout_t *parse_keyboard_layout(const char *language,
        }
     }
     fclose(f);
-
-    for (i = 0; i < MAX_NORMAL_KEYCODE; i++) {
-        if (k->keysym2numlock[i] != 1) {
-            k->keysym2numlock[i] = -keycode2numlock[k->keysym2keycode[i]];
-        }
-    }
-
-    for (i = 0; i < k->extra_count; i++) {
-        if (k->keysym2keycode_extra[i].numlock != 1) {
-            k->keysym2keycode_extra[i].numlock =
-                -keycode2numlock[k->keysym2keycode_extra[i].keycode];
-        }
-    }
-
-    free(keycode2numlock);
-
     return k;
 }
 
@@ -180,25 +143,3 @@ static int keysym2scancode(void *kbd_layout, int keysym)
     }
     return 0;
 }
-
-/**
- * Returns 1 if the given keysym requires numlock to be pressed, -1 if it
- * requires it to be cleared, and 0 otherwise.
- */
-static int keysym2numlock(void *kbd_layout, int keysym)
-{
-    kbd_layout_t *k = kbd_layout;
-    if (keysym < MAX_NORMAL_KEYCODE) {
-       return k->keysym2numlock[keysym];
-    } else {
-       int i;
-#ifdef XK_ISO_Left_Tab
-       if (keysym == XK_ISO_Left_Tab)
-           keysym = XK_Tab;
-#endif
-       for (i = 0; i < k->extra_count; i++)
-           if (k->keysym2keycode_extra[i].keysym == keysym)
-               return k->keysym2keycode_extra[i].numlock;
-    }
-    return 0;
-}
index 2a2b7d670da960403ecedc6f8f26f9e3747db63d..e667718e8de4d3d04a54b795ec3330ddc4e3be17 100644 (file)
@@ -1,36 +1,36 @@
-/ar/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/common/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/da/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/de/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/de-ch/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/en-gb/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/en-us/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/es/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/et/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/fi/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/fo/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/fr/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/fr-be/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/fr-ca/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/fr-ch/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/hr/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/hu/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/is/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/it/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/ja/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/lt/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/lv/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/mk/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/modifiers/1.2/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/nl/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/nl-be/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/no/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/pl/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/pt/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/pt-br/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/ru/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/sl/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/sv/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/th/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
-/tr/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
+/ar/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
+/common/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
+/da/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
+/de/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
+/de-ch/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
+/en-gb/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
+/en-us/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
+/es/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
+/et/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
+/fi/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
+/fo/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
+/fr/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
+/fr-be/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
+/fr-ca/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
+/fr-ch/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
+/hr/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
+/hu/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
+/is/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
+/it/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
+/ja/1.3/Thu May  3 17:18:01 2007//Trelease_0_9_0
+/lt/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
+/lv/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
+/mk/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
+/modifiers/1.2/Thu May  3 17:17:34 2007//Trelease_0_9_0
+/nl/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
+/nl-be/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
+/no/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
+/pl/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
+/pt/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
+/pt-br/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
+/ru/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
+/sl/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
+/sv/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
+/th/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
+/tr/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
 D
index bd48d406fa1b16a1721b34dc4bb6979acc4274da..eed9f4a4fb93e992c8c20b591822041f09711c7e 100644 (file)
@@ -1 +1 @@
-Nrelease_0_8_2
+Nrelease_0_9_0
index 770220c5882074874cac8e4bfd1f5da96fe71c66..6947cb124c6bad08166760fbfe183e962c304c83 100644 (file)
@@ -97,6 +97,7 @@ Eisu_toggle 0x3a shift
 Execute 0x54 shift
 Kanji 0x70
 backslash 0x73
+yen 0x7d
 bar 0x7d shift
 underscore 0x73 shift
 Henkan_Mode 0x79
index b7a93b0be6d057d415a83be0a9b7a4d650dcf453..96ca5826c291f649a37cae269f3f1be0d4368a4b 100644 (file)
@@ -26,6 +26,9 @@
 #include <sys/mman.h>
 #include <sys/ioctl.h>
 #endif
+#ifdef HOST_SOLARIS
+#include <sys/modctl.h>
+#endif
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdarg.h>
@@ -470,13 +473,17 @@ static int do_syscall(CPUState *env,
     selector = (env->star >> 32) & 0xffff;
 #ifdef __x86_64__
     if (env->hflags & HF_LMA_MASK) {
+        int code64;
+
         env->regs[R_ECX] = kenv->next_eip;
         env->regs[11] = env->eflags;
 
+        code64 = env->hflags & HF_CS64_MASK;
+
         cpu_x86_set_cpl(env, 0);
         cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc, 
                                0, 0xffffffff, 
-                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
+                               DESC_G_MASK | DESC_P_MASK |
                                DESC_S_MASK |
                                DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
         cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc, 
@@ -485,7 +492,7 @@ static int do_syscall(CPUState *env,
                                DESC_S_MASK |
                                DESC_W_MASK | DESC_A_MASK);
         env->eflags &= ~env->fmask;
-        if (env->hflags & HF_CS64_MASK)
+        if (code64)
             env->eip = env->lstar;
         else
             env->eip = env->cstar;
index 3fa681dbb0c4fd93fec62336c03d42b98329d994..7823add91786f42998f74c64dac924e858b5480a 100644 (file)
@@ -197,7 +197,7 @@ static void *load_at(int fd, int offset, int size)
 int load_elf(const char *filename, int64_t virt_to_phys_addend,
              uint64_t *pentry)
 {
-    int fd, data_order, must_swab, ret;
+    int fd, data_order, host_data_order, must_swab, ret;
     uint8_t e_ident[EI_NIDENT];
 
     fd = open(filename, O_RDONLY | O_BINARY);
@@ -218,7 +218,15 @@ int load_elf(const char *filename, int64_t virt_to_phys_addend,
     data_order = ELFDATA2LSB;
 #endif
     must_swab = data_order != e_ident[EI_DATA];
-    
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    host_data_order = ELFDATA2MSB;
+#else
+    host_data_order = ELFDATA2LSB;
+#endif
+    if (host_data_order != e_ident[EI_DATA])
+        return -1;
+
     lseek(fd, 0, SEEK_SET);
     if (e_ident[EI_CLASS] == ELFCLASS64) {
         ret = load_elf64(fd, virt_to_phys_addend, must_swab, pentry);
index 222142124394a6878db0ba4c67c76db24636cd2c..f3bfe0fbf1f453fb5409cd8640d7c7f4875ee38f 100644 (file)
@@ -56,6 +56,7 @@ typedef struct term_cmd_t {
 } term_cmd_t;
 
 static CharDriverState *monitor_hd;
+static int hide_banner;
 
 static term_cmd_t term_cmds[];
 static term_cmd_t info_cmds[];
@@ -113,6 +114,33 @@ void term_printf(const char *fmt, ...)
     va_end(ap);
 }
 
+void term_print_filename(const char *filename)
+{
+    int i;
+
+    for (i = 0; filename[i]; i++) {
+       switch (filename[i]) {
+       case ' ':
+       case '"':
+       case '\\':
+           term_printf("\\%c", filename[i]);
+           break;
+       case '\t':
+           term_printf("\\t");
+           break;
+       case '\r':
+           term_printf("\\r");
+           break;
+       case '\n':
+           term_printf("\\n");
+           break;
+       default:
+           term_printf("%c", filename[i]);
+           break;
+       }
+    }
+}
+
 #ifndef CONFIG_DM
 static int monitor_fprintf(FILE *stream, const char *fmt, ...)
 {
@@ -176,13 +204,16 @@ static void do_help(const char *name)
     help_cmd(name);
 }
 
-static void do_commit(void)
+static void do_commit(const char *device)
 {
-    int i;
-
+    int i, all_devices;
+    
+    all_devices = !strcmp(device, "all");
     for (i = 0; i < MAX_DISKS + MAX_SCSI_DISKS; i++) {
         if (bs_table[i]) {
-            bdrv_commit(bs_table[i]);
+            if (all_devices || 
+                !strcmp(bdrv_get_device_name(bs_table[i]), device))
+                bdrv_commit(bs_table[i]);
         }
     }
 }
@@ -390,18 +421,6 @@ static void do_log(const char *items)
 }
 
 #ifndef CONFIG_DM
-static void do_savevm(const char *filename)
-{
-    if (qemu_savevm(filename) < 0)
-        term_printf("I/O error when saving VM to '%s'\n", filename);
-}
-
-static void do_loadvm(const char *filename)
-{
-    if (qemu_loadvm(filename) < 0) 
-        term_printf("I/O error when loading VM from '%s'\n", filename);
-}
-
 static void do_stop(void)
 {
     vm_stop(EXCP_INTERRUPT);
@@ -417,7 +436,7 @@ static void do_gdbserver(int has_port, int port)
 {
     if (!has_port)
         port = DEFAULT_GDBSTUB_PORT;
-    if (gdbserver_start(port) < 0) {
+    if (gdbserver_start_port(port) < 0) {
         qemu_printf("Could not open gdbserver socket on port %d\n", port);
     } else {
         qemu_printf("Waiting gdb connection on port %d\n", port);
@@ -636,6 +655,36 @@ static void do_print(int count, int format, int size, unsigned int valh, unsigne
 #endif
     term_printf("\n");
 }
+
+static void do_memory_save(unsigned int valh, unsigned int vall, 
+                           uint32_t size, const char *filename)
+{
+    FILE *f;
+    target_long addr = GET_TLONG(valh, vall);
+    uint32_t l;
+    CPUState *env;
+    uint8_t buf[1024];
+
+    env = mon_get_cpu();
+    if (!env)
+        return;
+
+    f = fopen(filename, "wb");
+    if (!f) {
+        term_printf("could not open '%s'\n", filename);
+        return;
+    }
+    while (size != 0) {
+        l = sizeof(buf);
+        if (l > size)
+            l = size;
+        cpu_memory_rw_debug(env, addr, buf, l, 0);
+        fwrite(buf, 1, l, f);
+        addr += l;
+        size -= l;
+    }
+    fclose(f);
+}
 #endif /* !CONFIG_DM */
 
 static void do_sum(uint32_t start, uint32_t size)
@@ -1154,8 +1203,8 @@ static void do_wav_capture (const char *path,
 static term_cmd_t term_cmds[] = {
     { "help|?", "s?", do_help, 
       "[cmd]", "show the help" },
-    { "commit", "", do_commit, 
-      "", "commit changes to the disk images (if -snapshot is used)" },
+    { "commit", "s", do_commit, 
+      "device|all", "commit changes to the disk images (if -snapshot is used) or backing files" },
     { "info", "s?", do_info,
       "subcommand", "show various information about the system state" },
     { "q|quit", "", do_quit,
@@ -1169,10 +1218,12 @@ static term_cmd_t term_cmds[] = {
     { "log", "s", do_log,
       "item1[,...]", "activate logging of the specified items to '/tmp/qemu.log'" }, 
 #ifndef CONFIG_DM
-    { "savevm", "F", do_savevm,
-      "filename", "save the whole virtual machine state to 'filename'" }, 
-    { "loadvm", "F", do_loadvm,
-      "filename", "restore the whole virtual machine state from 'filename'" }, 
+    { "savevm", "s?", do_savevm,
+      "tag|id", "save a VM snapshot. If no tag or id are provided, a new snapshot is created" }, 
+    { "loadvm", "s", do_loadvm,
+      "tag|id", "restore a VM snapshot from its tag or id" }, 
+    { "delvm", "s", do_delvm,
+      "tag|id", "delete a VM snapshot from its tag or id" }, 
     { "stop", "", do_stop, 
       "", "stop emulation", },
     { "c|cont", "", do_cont, 
@@ -1213,6 +1264,8 @@ static term_cmd_t term_cmds[] = {
       "dx dy [dz]", "send mouse move events" },
     { "mouse_button", "i", do_mouse_button, 
       "state", "change mouse button state (1=L, 2=M, 4=R)" },
+    { "mouse_set", "i", do_mouse_set,
+      "index", "set which mouse device receives events" },
 #ifdef HAS_AUDIO
     { "wavcapture", "si?i?i?", do_wav_capture,
       "path [frequency bits channels]",
@@ -1220,6 +1273,10 @@ static term_cmd_t term_cmds[] = {
 #endif
      { "stopcapture", "i", do_stop_capture,
        "capture index", "stop capture" },
+#ifndef CONFIG_DM
+    { "memsave", "lis", do_memory_save, 
+      "addr size file", "save to disk virtual memory dump starting at 'addr' of size 'size'", },
+#endif /* !CONFIG_DM */
     { NULL, NULL, }, 
 };
 
@@ -1263,10 +1320,16 @@ static term_cmd_t info_cmds[] = {
     { "profile", "", do_info_profile,
       "", "show profiling information", },
     { "capture", "", do_info_capture,
-      "show capture information" },
+      "", "show capture information" },
+    { "snapshots", "", do_info_snapshots,
+      "", "show the currently saved VM snapshots" },
+    { "mice", "", do_info_mice,
+      "", "show which guest mouse is receiving events" },
+    { "vnc", "", do_info_vnc,
+      "", "show the vnc server status"},
 #ifdef CONFIG_DM
     { "hvmiopage", "", sp_info,
-      "", "show HVM device model shared page info", },
+      "", "show HVM device model shared page info" },
 #endif /* CONFIG_DM */
     { NULL, NULL, },
 };
@@ -2430,14 +2493,22 @@ static void monitor_start_input(void)
     readline_start("(HVMXen) ", 0, monitor_handle_command1, NULL);
 }
 
+static void term_event(void *opaque, int event)
+{
+    if (event != CHR_EVENT_RESET)
+       return;
+
+    if (!hide_banner)
+       term_printf("HVM device model. type 'q' to exit\n");
+    monitor_start_input();
+}
+
 void monitor_init(CharDriverState *hd, int show_banner)
 {
     monitor_hd = hd;
-    if (show_banner) {
-        term_printf("HVM device model. type 'q' to exit\n");
-    }
-    qemu_chr_add_read_handler(hd, term_can_read, term_read, NULL);
-    monitor_start_input();
+    hide_banner = !show_banner;
+
+    qemu_chr_add_handlers(hd, term_can_read, term_read, term_event, NULL);
 }
 
 /* XXX: use threads ? */
index ffa29fe8e4c812bba357b1f6612bb7b6886d47ee..d1eff8deb5cb0c2a529971c8a4b052d425c88554 100644 (file)
 #include <string.h>
 #include <errno.h>
 #include <unistd.h>
+#ifdef HOST_SOLARIS
+#include <sys/types.h>
+#include <sys/statvfs.h>
+#endif
 
 #include "cpu.h"
 #if defined(USE_KQEMU)
 #include "vl.h"
 #endif
 
-#if defined(__i386__) && !defined(CONFIG_SOFTMMU) && !defined(CONFIG_USER_ONLY)
-
-#include <sys/mman.h>
-#include <sys/ipc.h>
-
-/* When not using soft mmu, libc independant functions are needed for
-   the CPU core because it needs to use alternates stacks and
-   libc/thread incompatibles settings */
-
-#include <linux/unistd.h>
-
-#define QEMU_SYSCALL0(name) \
-{ \
-long __res; \
-__asm__ volatile ("int $0x80" \
-       : "=a" (__res) \
-       : "0" (__NR_##name)); \
-return __res; \
-}
-
-#define QEMU_SYSCALL1(name,arg1) \
-{ \
-long __res; \
-__asm__ volatile ("int $0x80" \
-       : "=a" (__res) \
-       : "0" (__NR_##name),"b" ((long)(arg1))); \
-return __res; \
-}
-
-#define QEMU_SYSCALL2(name,arg1,arg2) \
-{ \
-long __res; \
-__asm__ volatile ("int $0x80" \
-       : "=a" (__res) \
-       : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2))); \
-return __res; \
-}
-
-#define QEMU_SYSCALL3(name,arg1,arg2,arg3) \
-{ \
-long __res; \
-__asm__ volatile ("int $0x80" \
-       : "=a" (__res) \
-       : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
-                 "d" ((long)(arg3))); \
-return __res; \
-}
-
-#define QEMU_SYSCALL4(name,arg1,arg2,arg3,arg4) \
-{ \
-long __res; \
-__asm__ volatile ("int $0x80" \
-       : "=a" (__res) \
-       : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
-         "d" ((long)(arg3)),"S" ((long)(arg4))); \
-return __res; \
-} 
-
-#define QEMU_SYSCALL5(name,arg1,arg2,arg3,arg4,arg5) \
-{ \
-long __res; \
-__asm__ volatile ("int $0x80" \
-       : "=a" (__res) \
-       : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
-         "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5))); \
-return __res; \
-}
-
-#define QEMU_SYSCALL6(name,arg1,arg2,arg3,arg4,arg5,arg6) \
-{ \
-long __res; \
-__asm__ volatile ("push %%ebp ; movl %%eax,%%ebp ; movl %1,%%eax ; int $0x80 ; pop %%ebp" \
-       : "=a" (__res) \
-       : "i" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
-         "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5)), \
-         "0" ((long)(arg6))); \
-return __res; \
-}
-
-int qemu_write(int fd, const void *buf, size_t n)
-{
-    QEMU_SYSCALL3(write, fd, buf, n);
-}
-
-
-
-/****************************************************************/
-/* shmat replacement */
-
-int qemu_ipc(int call, unsigned long first, 
-            unsigned long second, unsigned long third, 
-            void *ptr, unsigned long fifth)
-{
-    QEMU_SYSCALL6(ipc, call, first, second, third, ptr, fifth);
-}
-
-#define SHMAT 21
-
-/* we must define shmat so that a specific address will be used when
-   mapping the X11 ximage */
-void *shmat(int shmid, const void *shmaddr, int shmflg)
-{
-    void *ptr;
-    int ret;
-    /* we give an address in the right memory area */
-    if (!shmaddr)
-        shmaddr = get_mmap_addr(8192 * 1024);
-    ret = qemu_ipc(SHMAT, shmid, shmflg, (unsigned long)&ptr, (void *)shmaddr, 0);
-    if (ret < 0)
-        return NULL;
-    return ptr;
-}
-
-/****************************************************************/
-/* sigaction bypassing the threads */
-
-static int kernel_sigaction(int signum, const struct qemu_sigaction *act, 
-                            struct qemu_sigaction *oldact, 
-                            int sigsetsize)
-{
-    QEMU_SYSCALL4(rt_sigaction, signum, act, oldact, sigsetsize);
-}
-
-int qemu_sigaction(int signum, const struct qemu_sigaction *act, 
-                   struct qemu_sigaction *oldact)
-{
-    return kernel_sigaction(signum, act, oldact, 8);
-}
-
-/****************************************************************/
-/* memory allocation */
-
-//#define DEBUG_MALLOC
-
-#define MALLOC_BASE       0xab000000
-#define PHYS_RAM_BASE     0xac000000
-
-#define MALLOC_ALIGN      16
-#define BLOCK_HEADER_SIZE 16
-
-typedef struct MemoryBlock {
-    struct MemoryBlock *next;
-    unsigned long size; /* size of block, including header */
-} MemoryBlock;
-
-static MemoryBlock *first_free_block;
-static unsigned long malloc_addr = MALLOC_BASE;
-
-static void *malloc_get_space(size_t size)
-{
-    void *ptr;
-    size = TARGET_PAGE_ALIGN(size);
-    ptr = mmap((void *)malloc_addr, size, 
-               PROT_WRITE | PROT_READ, 
-               MAP_PRIVATE | MAP_FIXED | MAP_ANON, -1, 0);
-    if (ptr == MAP_FAILED)
-        return NULL;
-    malloc_addr += size;
-    return ptr;
-}
-
-void *qemu_malloc(size_t size)
-{
-    MemoryBlock *mb, *mb1, **pmb;
-    void *ptr;
-    size_t size1, area_size;
-    
-    if (size == 0)
-        return NULL;
-
-    size = (size + BLOCK_HEADER_SIZE + MALLOC_ALIGN - 1) & ~(MALLOC_ALIGN - 1);
-    pmb = &first_free_block;
-    for(;;) {
-        mb = *pmb;
-        if (mb == NULL)
-            break;
-        if (size <= mb->size)
-            goto found;
-        pmb = &mb->next;
-    }
-    /* no big enough blocks found: get new space */
-    area_size = TARGET_PAGE_ALIGN(size);
-    mb = malloc_get_space(area_size);
-    if (!mb)
-        return NULL;
-    size1 = area_size - size;
-    if (size1 > 0) {
-        /* create a new free block */
-        mb1 = (MemoryBlock *)((uint8_t *)mb + size);
-        mb1->next = NULL;
-        mb1->size = size1;
-        *pmb = mb1;
-    }
-    goto the_end;
- found:
-    /* a free block was found: use it */
-    size1 = mb->size - size;
-    if (size1 > 0) {
-        /* create a new free block */
-        mb1 = (MemoryBlock *)((uint8_t *)mb + size);
-        mb1->next = mb->next;
-        mb1->size = size1;
-        *pmb = mb1;
-    } else {
-        /* suppress the first block */
-        *pmb = mb->next;
-    }
- the_end:
-    mb->size = size;
-    mb->next = NULL;
-    ptr = ((uint8_t *)mb + BLOCK_HEADER_SIZE);
-#ifdef DEBUG_MALLOC
-    qemu_printf("malloc: size=0x%x ptr=0x%lx\n", size, (unsigned long)ptr);
-#endif
-    return ptr;
-}
-
-void qemu_free(void *ptr)
-{
-    MemoryBlock *mb;
-
-    if (!ptr)
-        return;
-    mb = (MemoryBlock *)((uint8_t *)ptr - BLOCK_HEADER_SIZE);
-    mb->next = first_free_block;
-    first_free_block = mb;
-}
-
-/****************************************************************/
-/* virtual memory allocation */
-
-unsigned long mmap_addr = PHYS_RAM_BASE;
-
-void *get_mmap_addr(unsigned long size)
-{
-    unsigned long addr;
-    addr = mmap_addr;
-    mmap_addr += ((size + 4095) & ~4095) + 4096;
-    return (void *)addr;
-}
-
-#else
-
 #ifdef _WIN32
 #include <windows.h>
 #elif defined(_BSD)
@@ -284,16 +45,6 @@ void *get_mmap_addr(unsigned long size)
 #include <malloc.h>
 #endif
 
-int qemu_write(int fd, const void *buf, size_t n)
-{
-    int ret;
-    ret = write(fd, buf, n);
-    if (ret < 0)
-        return -errno;
-    else
-        return ret;
-}
-
 void *get_mmap_addr(unsigned long size)
 {
     return NULL;
@@ -339,13 +90,22 @@ void *kqemu_vmalloc(size_t size)
     const char *tmpdir;
     char phys_ram_file[1024];
     void *ptr;
+#ifdef HOST_SOLARIS
+    struct statvfs stfs;
+#else
     struct statfs stfs;
+#endif
 
     if (phys_ram_fd < 0) {
         tmpdir = getenv("QEMU_TMPDIR");
         if (!tmpdir)
+#ifdef HOST_SOLARIS
+            tmpdir = "/tmp";
+        if (statvfs(tmpdir, &stfs) == 0) {
+#else
             tmpdir = "/dev/shm";
         if (statfs(tmpdir, &stfs) == 0) {
+#endif
             int64_t free_space;
             int ram_mb;
 
@@ -373,7 +133,8 @@ void *kqemu_vmalloc(size_t size)
         }
         snprintf(phys_ram_file, sizeof(phys_ram_file), "%s/qemuXXXXXX", 
                  tmpdir);
-        if (mkstemp(phys_ram_file) < 0) {
+        phys_ram_fd = mkstemp(phys_ram_file);
+        if (phys_ram_fd < 0) {
             fprintf(stderr, 
                     "warning: could not create temporary file in '%s'.\n"
                     "Use QEMU_TMPDIR to select a directory in a tmpfs filesystem.\n"
@@ -381,18 +142,13 @@ void *kqemu_vmalloc(size_t size)
                     tmpdir);
             snprintf(phys_ram_file, sizeof(phys_ram_file), "%s/qemuXXXXXX", 
                      "/tmp");
-            if (mkstemp(phys_ram_file) < 0) {
+            phys_ram_fd = mkstemp(phys_ram_file);
+            if (phys_ram_fd < 0) {
                 fprintf(stderr, "Could not create temporary memory file '%s'\n", 
                         phys_ram_file);
                 exit(1);
             }
         }
-        phys_ram_fd = open(phys_ram_file, O_CREAT | O_TRUNC | O_RDWR, 0600);
-        if (phys_ram_fd < 0) {
-            fprintf(stderr, "Could not open temporary memory file '%s'\n", 
-                    phys_ram_file);
-            exit(1);
-        }
         unlink(phys_ram_file);
     }
     size = (size + 4095) & ~4095;
@@ -441,8 +197,6 @@ void qemu_vfree(void *ptr)
 
 #endif
 
-#endif
-
 void *qemu_mallocz(size_t size)
 {
     void *ptr;
@@ -462,181 +216,3 @@ char *qemu_strdup(const char *str)
     strcpy(ptr, str);
     return ptr;
 }
-
-/****************************************************************/
-/* printf support */
-
-static inline int qemu_isdigit(int c)
-{
-    return c >= '0' && c <= '9';
-}
-
-#define OUTCHAR(c)     (buflen > 0? (--buflen, *buf++ = (c)): 0)
-
-/* from BSD ppp sources */
-int qemu_vsnprintf(char *buf, int buflen, const char *fmt, va_list args)
-{
-    int c, i, n;
-    int width, prec, fillch;
-    int base, len, neg;
-    unsigned long val = 0;
-    const char *f;
-    char *str, *buf0;
-    char num[32];
-    static const char hexchars[] = "0123456789abcdef";
-
-    buf0 = buf;
-    --buflen;
-    while (buflen > 0) {
-       for (f = fmt; *f != '%' && *f != 0; ++f)
-           ;
-       if (f > fmt) {
-           len = f - fmt;
-           if (len > buflen)
-               len = buflen;
-           memcpy(buf, fmt, len);
-           buf += len;
-           buflen -= len;
-           fmt = f;
-       }
-       if (*fmt == 0)
-           break;
-       c = *++fmt;
-       width = prec = 0;
-       fillch = ' ';
-       if (c == '0') {
-           fillch = '0';
-           c = *++fmt;
-       }
-       if (c == '*') {
-           width = va_arg(args, int);
-           c = *++fmt;
-       } else {
-           while (qemu_isdigit(c)) {
-               width = width * 10 + c - '0';
-               c = *++fmt;
-           }
-       }
-       if (c == '.') {
-           c = *++fmt;
-           if (c == '*') {
-               prec = va_arg(args, int);
-               c = *++fmt;
-           } else {
-               while (qemu_isdigit(c)) {
-                   prec = prec * 10 + c - '0';
-                   c = *++fmt;
-               }
-           }
-       }
-        /* modifiers */
-        switch(c) {
-        case 'l':
-            c = *++fmt;
-            break;
-        default:
-            break;
-        }
-        str = 0;
-       base = 0;
-       neg = 0;
-       ++fmt;
-       switch (c) {
-       case 'd':
-           i = va_arg(args, int);
-           if (i < 0) {
-               neg = 1;
-               val = -i;
-           } else
-               val = i;
-           base = 10;
-           break;
-       case 'o':
-           val = va_arg(args, unsigned int);
-           base = 8;
-           break;
-       case 'x':
-       case 'X':
-           val = va_arg(args, unsigned int);
-           base = 16;
-           break;
-       case 'p':
-           val = (unsigned long) va_arg(args, void *);
-           base = 16;
-           neg = 2;
-           break;
-       case 's':
-           str = va_arg(args, char *);
-           break;
-       case 'c':
-           num[0] = va_arg(args, int);
-           num[1] = 0;
-           str = num;
-           break;
-       default:
-           *buf++ = '%';
-           if (c != '%')
-               --fmt;          /* so %z outputs %z etc. */
-           --buflen;
-           continue;
-       }
-       if (base != 0) {
-           str = num + sizeof(num);
-           *--str = 0;
-           while (str > num + neg) {
-               *--str = hexchars[val % base];
-               val = val / base;
-               if (--prec <= 0 && val == 0)
-                   break;
-           }
-           switch (neg) {
-           case 1:
-               *--str = '-';
-               break;
-           case 2:
-               *--str = 'x';
-               *--str = '0';
-               break;
-           }
-           len = num + sizeof(num) - 1 - str;
-       } else {
-           len = strlen(str);
-           if (prec > 0 && len > prec)
-               len = prec;
-       }
-       if (width > 0) {
-           if (width > buflen)
-               width = buflen;
-           if ((n = width - len) > 0) {
-               buflen -= n;
-               for (; n > 0; --n)
-                   *buf++ = fillch;
-           }
-       }
-       if (len > buflen)
-           len = buflen;
-       memcpy(buf, str, len);
-       buf += len;
-       buflen -= len;
-    }
-    *buf = 0;
-    return buf - buf0;
-}
-
-void qemu_vprintf(const char *fmt, va_list ap)
-{
-    char buf[1024];
-    int len;
-    
-    len = qemu_vsnprintf(buf, sizeof(buf), fmt, ap);
-    qemu_write(1, buf, len);
-}
-
-void qemu_printf(const char *fmt, ...)
-{
-    va_list ap;
-    va_start(ap, fmt);
-    qemu_vprintf(fmt, ap);
-    va_end(ap);
-}
-
index 29a261cbd501146c6f0509a508f7f9422d9ae4cf..325baf14eb47ca46ad50cd3d1df11dfb3afefe15 100644 (file)
@@ -3,9 +3,7 @@
 
 #include <stdarg.h>
 
-int qemu_vsnprintf(char *buf, int buflen, const char *fmt, va_list args);
-void qemu_vprintf(const char *fmt, va_list ap);
-void qemu_printf(const char *fmt, ...);
+#define qemu_printf printf
 
 void *qemu_malloc(size_t size);
 void *qemu_mallocz(size_t size);
@@ -17,39 +15,4 @@ void qemu_vfree(void *ptr);
 
 void *get_mmap_addr(unsigned long size);
 
-/* specific kludges for OS compatibility (should be moved elsewhere) */
-#if defined(__i386__) && !defined(CONFIG_SOFTMMU) && !defined(CONFIG_USER_ONLY)
-
-/* disabled pthread version of longjmp which prevent us from using an
-   alternative signal stack */
-extern void __longjmp(jmp_buf env, int val);
-#define longjmp __longjmp
-
-#include <signal.h>
-
-struct siginfo;
-
-/* NOTE: it works only because the glibc sigset_t is >= kernel sigset_t */
-struct qemu_sigaction {
-    union {
-        void (*_sa_handler)(int);
-        void (*_sa_sigaction)(int, struct siginfo *, void *);
-    } _u;
-    unsigned long sa_flags;
-    void (*sa_restorer)(void);
-    sigset_t sa_mask;          /* mask last for extensibility */
-};
-
-int qemu_sigaction(int signum, const struct qemu_sigaction *act, 
-                   struct qemu_sigaction *oldact);
-
-#undef sigaction
-#undef sa_handler
-#undef sa_sigaction
-#define sigaction qemu_sigaction
-#define sa_handler     _u._sa_handler
-#define sa_sigaction   _u._sa_sigaction
-
-#endif
-
 #endif
index 2dfb8c2fad7ed44c20fb56d189022fd6ea6d65ef..61965bbd986196d97a38dd29b4eea47a544ae1dc 100644 (file)
@@ -1,7 +1,7 @@
 Index: ioemu/hw/piix4acpi.c
 ===================================================================
---- ioemu.orig/hw/piix4acpi.c  2007-05-02 15:59:27.000000000 +0100
-+++ ioemu/hw/piix4acpi.c       2007-05-02 16:02:29.000000000 +0100
+--- ioemu.orig/hw/piix4acpi.c  2007-05-03 19:46:01.000000000 +0100
++++ ioemu/hw/piix4acpi.c       2007-05-03 19:46:09.000000000 +0100
 @@ -45,6 +45,10 @@
  #define GBL_RLS           (1 << 2)
  #define SLP_EN            (1 << 13)
index afbe4e03aac99f1c18a46825a708d1c0eb14d44c..5de41c87e8de31fec438989b32f97754c02c8834 100644 (file)
@@ -1,20 +1,20 @@
 Index: ioemu/Makefile.target
 ===================================================================
---- ioemu.orig/Makefile.target 2007-05-03 15:06:42.000000000 +0100
-+++ ioemu/Makefile.target      2007-05-03 15:07:21.000000000 +0100
-@@ -358,6 +358,7 @@
+--- ioemu.orig/Makefile.target 2007-05-09 13:47:48.000000000 +0100
++++ ioemu/Makefile.target      2007-05-09 13:53:57.000000000 +0100
+@@ -389,6 +389,7 @@
  VL_OBJS+= fdc.o mc146818rtc.o serial.o pc.o
  VL_OBJS+= cirrus_vga.o mixeng.o parallel.o acpi.o piix_pci.o
- VL_OBJS+= usb-uhci.o
+ VL_OBJS+= usb-uhci.o smbus_eeprom.o
 +VL_OBJS+= piix4acpi.o
DEFINES += -DHAS_AUDIO
CPPFLAGS += -DHAS_AUDIO
  endif
  ifeq ($(TARGET_BASE_ARCH), ppc)
 Index: ioemu/hw/pc.c
 ===================================================================
---- ioemu.orig/hw/pc.c 2007-05-03 15:06:42.000000000 +0100
-+++ ioemu/hw/pc.c      2007-05-03 15:07:21.000000000 +0100
-@@ -873,13 +873,19 @@
+--- ioemu.orig/hw/pc.c 2007-05-09 13:47:48.000000000 +0100
++++ ioemu/hw/pc.c      2007-05-09 13:53:56.000000000 +0100
+@@ -727,10 +727,15 @@
  
      cmos_init(ram_size, boot_device, bs_table);
  
@@ -29,27 +29,20 @@ Index: ioemu/hw/pc.c
  
 +#ifndef CONFIG_DM
      if (pci_enabled && acpi_enabled) {
+         uint8_t *eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */
          piix4_pm_init(pci_bus, piix3_devfn + 3);
+@@ -740,6 +745,7 @@
+             piix4_smbus_register_device(eeprom, 0x50 + i);
+         }
      }
 +#endif /* !CONFIG_DM */
- #if 0
-     /* ??? Need to figure out some way for the user to
-@@ -902,8 +908,10 @@
-     /* XXX: should be done in the Bochs BIOS */
-     if (pci_enabled) {
-         pci_bios_init();
-+#ifndef CONFIG_DM
-         if (acpi_enabled)
-             acpi_bios_init();
-+#endif /* !CONFIG_DM */
-     }
- }
+     
+     if (i440fx_state) {
+         i440fx_init_memory_mappings(i440fx_state);
 Index: ioemu/hw/piix4acpi.c
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ ioemu/hw/piix4acpi.c       2007-05-03 15:07:31.000000000 +0100
++++ ioemu/hw/piix4acpi.c       2007-05-09 13:54:18.000000000 +0100
 @@ -0,0 +1,186 @@
 +/*
 + * PIIX4 ACPI controller emulation
@@ -235,38 +228,38 @@ Index: ioemu/hw/piix4acpi.c
 +    pci_conf[0x43] = 0x00;
 +    d->pm1_control = SCI_EN;
 +
-+    acpi_map(d, 0, 0x1f40, 0x10, PCI_ADDRESS_SPACE_IO);
++    acpi_map((PCIDevice *)d, 0, 0x1f40, 0x10, PCI_ADDRESS_SPACE_IO);
 +}
 Index: ioemu/vl.c
 ===================================================================
---- ioemu.orig/vl.c    2007-05-03 15:06:42.000000000 +0100
-+++ ioemu/vl.c 2007-05-03 15:07:21.000000000 +0100
-@@ -157,7 +157,7 @@
+--- ioemu.orig/vl.c    2007-05-09 13:47:48.000000000 +0100
++++ ioemu/vl.c 2007-05-09 13:53:57.000000000 +0100
+@@ -168,7 +168,7 @@
  #else
  #define MAX_CPUS 1
  #endif
 -int acpi_enabled = 1;
 +int acpi_enabled = 0;
  int fd_bootchk = 1;
- extern int vcpus;
-@@ -5415,6 +5415,7 @@
+ int no_reboot = 0;
+ int daemonize = 0;
+@@ -6313,6 +6313,7 @@
+          "-daemonize      daemonize QEMU after initializing\n"
  #endif
-            "-loadvm file    start right away with a saved state (loadvm in monitor)\n"
-          "-vnc display    start a VNC server on display\n"
+          "-option-rom rom load a file, rom, into the option ROM space\n"
 +           "-acpi           disable or enable ACPI of HVM domain \n"
             "\n"
             "During emulation, the following keys are useful:\n"
             "ctrl-alt-f      toggle full screen\n"
-@@ -5499,6 +5500,7 @@
+@@ -6402,6 +6403,7 @@
+     ,
      QEMU_OPTION_d,
      QEMU_OPTION_vcpus,
 +    QEMU_OPTION_acpi,
  };
  
  typedef struct QEMUOption {
-@@ -5581,6 +5583,7 @@
+@@ -6494,6 +6496,7 @@
      
      { "d", HAS_ARG, QEMU_OPTION_d },
      { "vcpus", 1, QEMU_OPTION_vcpus },
@@ -274,7 +267,7 @@ Index: ioemu/vl.c
      { NULL },
  };
  
-@@ -6322,6 +6325,9 @@
+@@ -7258,6 +7261,9 @@
                  vcpus = atoi(optarg);
                  fprintf(logfile, "qemu: the number of cpus is %d\n", vcpus);
                  break;
@@ -286,19 +279,19 @@ Index: ioemu/vl.c
      }
 Index: ioemu/vl.h
 ===================================================================
---- ioemu.orig/vl.h    2007-05-03 15:06:42.000000000 +0100
-+++ ioemu/vl.h 2007-05-03 15:07:21.000000000 +0100
-@@ -168,6 +168,7 @@
+--- ioemu.orig/vl.h    2007-05-09 13:47:48.000000000 +0100
++++ ioemu/vl.h 2007-05-09 13:53:57.000000000 +0100
+@@ -173,6 +173,7 @@
  extern int kqemu_allowed;
  extern int win2k_install_hack;
  extern int usb_enabled;
 +extern int acpi_enabled;
  extern int smp_cpus;
- /* XXX: make it dynamic */
-@@ -924,6 +925,9 @@
- void piix4_pm_init(PCIBus *bus, int devfn);
void acpi_bios_init(void);
+ extern int no_quit;
+ extern int semihosting_enabled;
+@@ -1079,6 +1080,9 @@
+ /* smbus_eeprom.c */
SMBusDevice *smbus_eeprom_device_init(uint8_t addr, uint8_t *buf);
  
 +/* piix4acpi.c */
 +extern void pci_piix4_acpi_init(PCIBus *bus, int devfn);
@@ -306,35 +299,3 @@ Index: ioemu/vl.h
  /* pc.c */
  extern QEMUMachine pc_machine;
  extern QEMUMachine isapc_machine;
-Index: ioemu/hw/piix_pci.c
-===================================================================
---- ioemu.orig/hw/piix_pci.c   2007-05-03 15:06:42.000000000 +0100
-+++ ioemu/hw/piix_pci.c        2007-05-03 15:07:13.000000000 +0100
-@@ -241,7 +241,7 @@
- static uint32_t pci_bios_io_addr;
- static uint32_t pci_bios_mem_addr;
- /* host irqs corresponding to PCI irqs A-D */
--static uint8_t pci_irqs[4] = { 11, 9, 11, 9 };
-+static uint8_t pci_irqs[4] = { 10, 11, 10, 11 };
- static void pci_config_writel(PCIDevice *d, uint32_t addr, uint32_t val)
- {
-@@ -336,6 +336,18 @@
-             pci_set_io_region_addr(d, 3, 0x374);
-         }
-         break;
-+    case 0x0680:
-+        if (vendor_id == 0x8086 && device_id == 0x7113) {
-+            /*
-+             * PIIX4 ACPI PM.
-+             * Special device with special PCI config space. No ordinary BARs.
-+             */
-+            pci_config_writew(d, 0x20, 0x0000); // No smb bus IO enable
-+            pci_config_writew(d, 0x22, 0x0000);
-+            pci_config_writew(d, 0x3c, 0x0009); // Hardcoded IRQ9
-+            pci_config_writew(d, 0x3d, 0x0001);
-+        }
-+        break;
-     case 0x0300:
-         if (vendor_id != 0x1234)
-             goto default_map;
index 537048f7b0a4baf8b1fdfaa1cc4abc6073470a84..4f28ae5662ab40091029044c05b429cd66beac9f 100644 (file)
@@ -1,7 +1,7 @@
 Index: ioemu/hw/piix4acpi.c
 ===================================================================
---- ioemu.orig/hw/piix4acpi.c  2007-05-02 15:59:22.000000000 +0100
-+++ ioemu/hw/piix4acpi.c       2007-05-02 15:59:27.000000000 +0100
+--- ioemu.orig/hw/piix4acpi.c  2007-05-03 19:36:00.000000000 +0100
++++ ioemu/hw/piix4acpi.c       2007-05-03 19:46:01.000000000 +0100
 @@ -24,26 +24,26 @@
   */
  
index 4cf2a8d47a32fe70b933ce31fa03a32c61ecd978..a447c6bac96f91f7923e08b7227d000a7ba11204 100644 (file)
@@ -1,8 +1,8 @@
 Index: ioemu/monitor.c
 ===================================================================
---- ioemu.orig/monitor.c       2007-05-03 14:54:59.000000000 +0100
-+++ ioemu/monitor.c    2007-05-03 14:55:01.000000000 +0100
-@@ -308,6 +308,7 @@
+--- ioemu.orig/monitor.c       2007-05-03 19:01:49.000000000 +0100
++++ ioemu/monitor.c    2007-05-03 19:12:02.000000000 +0100
+@@ -339,6 +339,7 @@
  
  static void do_quit(void)
  {
@@ -12,8 +12,8 @@ Index: ioemu/monitor.c
  
 Index: ioemu/target-i386-dm/helper2.c
 ===================================================================
---- ioemu.orig/target-i386-dm/helper2.c        2007-05-03 14:55:00.000000000 +0100
-+++ ioemu/target-i386-dm/helper2.c     2007-05-03 14:55:01.000000000 +0100
+--- ioemu.orig/target-i386-dm/helper2.c        2007-05-03 19:12:00.000000000 +0100
++++ ioemu/target-i386-dm/helper2.c     2007-05-03 19:12:02.000000000 +0100
 @@ -549,5 +549,26 @@
          /* Wait up to 10 msec. */
          main_loop_wait(10);
@@ -43,9 +43,9 @@ Index: ioemu/target-i386-dm/helper2.c
 +}
 Index: ioemu/vl.h
 ===================================================================
---- ioemu.orig/vl.h    2007-05-03 14:55:00.000000000 +0100
-+++ ioemu/vl.h 2007-05-03 14:55:01.000000000 +0100
-@@ -1190,4 +1190,7 @@
+--- ioemu.orig/vl.h    2007-05-03 19:12:00.000000000 +0100
++++ ioemu/vl.h 2007-05-03 19:12:02.000000000 +0100
+@@ -1410,4 +1410,7 @@
  void kqemu_record_dump(void);
  
  extern char domain_name[];
index de9ab41a7de84f4c934ccc81e343a7b8a9489f44..93e825f3a5db9594c10c2cd3e317353b2db468cd 100644 (file)
@@ -1,7 +1,7 @@
 Index: ioemu/target-i386-dm/helper2.c
 ===================================================================
---- ioemu.orig/target-i386-dm/helper2.c        2007-05-03 14:54:46.000000000 +0100
-+++ ioemu/target-i386-dm/helper2.c     2007-05-03 14:55:00.000000000 +0100
+--- ioemu.orig/target-i386-dm/helper2.c        2007-05-09 13:43:01.000000000 +0100
++++ ioemu/target-i386-dm/helper2.c     2007-05-09 13:44:09.000000000 +0100
 @@ -127,6 +127,22 @@
  /* called from main_cpu_reset */
  void cpu_reset(CPUX86State *env)
@@ -44,9 +44,9 @@ Index: ioemu/target-i386-dm/helper2.c
  }
 Index: ioemu/vl.c
 ===================================================================
---- ioemu.orig/vl.c    2007-05-03 14:55:00.000000000 +0100
-+++ ioemu/vl.c 2007-05-03 14:55:00.000000000 +0100
-@@ -4957,7 +4957,7 @@
+--- ioemu.orig/vl.c    2007-05-09 13:43:02.000000000 +0100
++++ ioemu/vl.c 2007-05-09 13:44:20.000000000 +0100
+@@ -5843,7 +5843,7 @@
  } QEMUResetEntry;
  
  static QEMUResetEntry *first_reset_entry;
@@ -55,11 +55,20 @@ Index: ioemu/vl.c
  int shutdown_requested;
  static int powerdown_requested;
  
+@@ -5861,7 +5861,7 @@
+     *pre = re;
+ }
+-static void qemu_system_reset(void)
++void qemu_system_reset(void)
+ {
+     QEMUResetEntry *re;
 Index: ioemu/vl.h
 ===================================================================
---- ioemu.orig/vl.h    2007-05-03 14:55:00.000000000 +0100
-+++ ioemu/vl.h 2007-05-03 14:55:00.000000000 +0100
-@@ -131,6 +131,7 @@
+--- ioemu.orig/vl.h    2007-05-09 13:43:01.000000000 +0100
++++ ioemu/vl.h 2007-05-09 13:44:09.000000000 +0100
+@@ -136,6 +136,7 @@
  
  void qemu_register_reset(QEMUResetHandler *func, void *opaque);
  void qemu_system_reset_request(void);
@@ -67,7 +76,7 @@ Index: ioemu/vl.h
  void qemu_system_shutdown_request(void);
  void qemu_system_powerdown_request(void);
  #if !defined(TARGET_SPARC)
-@@ -140,6 +141,8 @@
+@@ -145,6 +146,8 @@
  void qemu_system_powerdown(void);
  #endif
  
index f45756cc8d9a5139f24879c9a941ce006e147e5d..91a8d96e2941536b5e2dedf896a7352be52dff25 100644 (file)
@@ -1,7 +1,7 @@
 Index: ioemu/hw/mc146818rtc.c
 ===================================================================
---- ioemu.orig/hw/mc146818rtc.c        2007-05-03 15:38:35.000000000 +0100
-+++ ioemu/hw/mc146818rtc.c     2007-05-03 15:38:45.000000000 +0100
+--- ioemu.orig/hw/mc146818rtc.c        2007-05-09 14:12:16.000000000 +0100
++++ ioemu/hw/mc146818rtc.c     2007-05-09 14:12:43.000000000 +0100
 @@ -178,10 +178,27 @@
      }
  }
@@ -44,11 +44,19 @@ Index: ioemu/hw/mc146818rtc.c
  }
  
  static void rtc_copy_date(RTCState *s)
+@@ -392,6 +415,7 @@
+     /* set the CMOS date */
+     time(&ti);
++    ti += timeoffset;
+     if (rtc_utc)
+         tm = gmtime(&ti);
+     else
 Index: ioemu/hw/pc.c
 ===================================================================
---- ioemu.orig/hw/pc.c 2007-05-03 15:38:44.000000000 +0100
-+++ ioemu/hw/pc.c      2007-05-03 15:38:45.000000000 +0100
-@@ -159,7 +159,7 @@
+--- ioemu.orig/hw/pc.c 2007-05-09 14:12:16.000000000 +0100
++++ ioemu/hw/pc.c      2007-05-09 14:12:43.000000000 +0100
+@@ -160,7 +160,7 @@
  }
  
  /* hd_table must contain 4 block drivers */
@@ -57,15 +65,7 @@ Index: ioemu/hw/pc.c
  {
      RTCState *s = rtc_state;
      int val;
-@@ -170,6 +170,7 @@
-     /* set the CMOS date */
-     time(&ti);
-+    ti += timeoffset;
-     if (rtc_utc)
-         tm = gmtime(&ti);
-     else
-@@ -619,7 +620,7 @@
+@@ -454,7 +454,7 @@
  static void pc_init1(uint64_t ram_size, int vga_ram_size, int boot_device,
                       DisplayState *ds, const char **fd_filename, int snapshot,
                       const char *kernel_filename, const char *kernel_cmdline,
@@ -74,7 +74,7 @@ Index: ioemu/hw/pc.c
                       int pci_enabled)
  {
  #ifndef NOBIOS
-@@ -871,7 +872,7 @@
+@@ -725,7 +725,7 @@
  
      floppy_controller = fdctrl_init(6, 2, 0, 0x3f0, fd_table);
  
@@ -83,7 +83,7 @@ Index: ioemu/hw/pc.c
  
      /* using PIIX4 acpi model */
      if (pci_enabled && acpi_enabled)
-@@ -920,12 +921,13 @@
+@@ -774,12 +774,13 @@
                          int snapshot, 
                          const char *kernel_filename, 
                          const char *kernel_cmdline,
@@ -99,7 +99,7 @@ Index: ioemu/hw/pc.c
  }
  
  static void pc_init_isa(uint64_t ram_size, int vga_ram_size, int boot_device,
-@@ -933,12 +935,13 @@
+@@ -787,12 +788,13 @@
                          int snapshot, 
                          const char *kernel_filename, 
                          const char *kernel_cmdline,
@@ -117,9 +117,9 @@ Index: ioemu/hw/pc.c
  QEMUMachine pc_machine = {
 Index: ioemu/vl.c
 ===================================================================
---- ioemu.orig/vl.c    2007-05-03 15:38:45.000000000 +0100
-+++ ioemu/vl.c 2007-05-03 15:38:45.000000000 +0100
-@@ -167,6 +167,8 @@
+--- ioemu.orig/vl.c    2007-05-09 14:12:43.000000000 +0100
++++ ioemu/vl.c 2007-05-09 14:12:43.000000000 +0100
+@@ -184,6 +184,8 @@
  
  int xc_handle;
  
@@ -128,23 +128,23 @@ Index: ioemu/vl.c
  char domain_name[1024] = { 'H','V', 'M', 'X', 'E', 'N', '-'};
  extern int domid;
  
-@@ -5435,6 +5437,7 @@
+@@ -6329,6 +6331,7 @@
             "-vncviewer      start a vncviewer process for this domain\n"
             "-vncunused      bind the VNC server to an unused port\n"
             "-vnclisten      bind the VNC server to this address\n"
 +           "-timeoffset     time offset (in seconds) from local time\n"
-            "-acpi           disable or enable ACPI of HVM domain \n"
-            "\n"
-            "During emulation, the following keys are useful:\n"
-@@ -5522,6 +5525,7 @@
+ #ifndef _WIN32
+          "-daemonize      daemonize QEMU after initializing\n"
+ #endif
+@@ -6425,6 +6428,7 @@
+     ,
      QEMU_OPTION_d,
      QEMU_OPTION_vcpus,
 +    QEMU_OPTION_timeoffset,
      QEMU_OPTION_acpi,
      QEMU_OPTION_vncviewer,
      QEMU_OPTION_vncunused,
-@@ -5613,6 +5617,7 @@
+@@ -6526,6 +6530,7 @@
      
      { "d", HAS_ARG, QEMU_OPTION_d },
      { "vcpus", 1, QEMU_OPTION_vcpus },
@@ -152,7 +152,7 @@ Index: ioemu/vl.c
      { "acpi", 0, QEMU_OPTION_acpi },
      { NULL },
  };
-@@ -6377,6 +6382,9 @@
+@@ -7313,6 +7318,9 @@
                  vcpus = atoi(optarg);
                  fprintf(logfile, "qemu: the number of cpus is %d\n", vcpus);
                  break;
@@ -162,7 +162,7 @@ Index: ioemu/vl.c
              case QEMU_OPTION_acpi:
                  acpi_enabled = 1;
                  break;
-@@ -6531,6 +6539,9 @@
+@@ -7545,6 +7553,9 @@
      }
      free(page_array);
  #endif
@@ -172,7 +172,7 @@ Index: ioemu/vl.c
  #else  /* !CONFIG_DM */
  
      phys_ram_base = qemu_vmalloc(phys_ram_size);
-@@ -6662,7 +6673,8 @@
+@@ -7681,7 +7692,8 @@
  
      machine->init(ram_size, vga_ram_size, boot_device,
                    ds, fd_filename, snapshot,
@@ -184,9 +184,9 @@ Index: ioemu/vl.c
      if (usb_enabled) {
 Index: ioemu/vl.h
 ===================================================================
---- ioemu.orig/vl.h    2007-05-03 15:38:45.000000000 +0100
-+++ ioemu/vl.h 2007-05-03 15:38:45.000000000 +0100
-@@ -581,7 +581,7 @@
+--- ioemu.orig/vl.h    2007-05-09 14:12:43.000000000 +0100
++++ ioemu/vl.h 2007-05-09 14:12:43.000000000 +0100
+@@ -708,7 +708,7 @@
                                   int boot_device,
               DisplayState *ds, const char **fd_filename, int snapshot,
               const char *kernel_filename, const char *kernel_cmdline,
@@ -195,7 +195,7 @@ Index: ioemu/vl.h
  
  typedef struct QEMUMachine {
      const char *name;
-@@ -1216,6 +1216,10 @@
+@@ -1435,6 +1435,10 @@
  int xenstore_vm_write(int domid, char *key, char *val);
  char *xenstore_vm_read(int domid, char *key, int *len);
  
@@ -208,8 +208,8 @@ Index: ioemu/vl.h
  extern char domain_name[];
 Index: ioemu/target-i386-dm/helper2.c
 ===================================================================
---- ioemu.orig/target-i386-dm/helper2.c        2007-05-03 15:38:44.000000000 +0100
-+++ ioemu/target-i386-dm/helper2.c     2007-05-03 15:38:45.000000000 +0100
+--- ioemu.orig/target-i386-dm/helper2.c        2007-05-09 14:12:16.000000000 +0100
++++ ioemu/target-i386-dm/helper2.c     2007-05-09 14:12:43.000000000 +0100
 @@ -74,6 +74,8 @@
  
  int xc_handle;
index 2d27d6247273b50c6ceda660ac9830c615c7c4fc..235e78e8af1234ea71caafe0cb74e58356f13ecb 100644 (file)
@@ -17,9 +17,9 @@ Signed-off-by: Keir Fraser <keir@xensource.com>
 
 Index: ioemu/Makefile.target
 ===================================================================
---- ioemu.orig/Makefile.target 2006-12-20 15:04:55.000000000 +0000
-+++ ioemu/Makefile.target      2006-12-20 15:08:16.000000000 +0000
-@@ -296,9 +296,9 @@
+--- ioemu.orig/Makefile.target 2007-05-09 13:56:55.000000000 +0100
++++ ioemu/Makefile.target      2007-05-09 13:56:55.000000000 +0100
+@@ -325,9 +325,9 @@
  
  # qemu-dm objects
  ifeq ($(ARCH),ia64)
@@ -31,19 +31,19 @@ Index: ioemu/Makefile.target
  endif
  
  all: $(PROGS)
-@@ -364,7 +364,7 @@
+@@ -395,7 +395,7 @@
  else
  VL_OBJS+= fdc.o serial.o pc.o
  endif
 -VL_OBJS+= cirrus_vga.o mixeng.o parallel.o acpi.o piix_pci.o
 +VL_OBJS+= cirrus_vga.o mixeng.o parallel.o acpi.o
- VL_OBJS+= usb-uhci.o
+ VL_OBJS+= usb-uhci.o smbus_eeprom.o
  VL_OBJS+= piix4acpi.o
  VL_OBJS+= xenstore.o
 Index: ioemu/target-i386-dm/i8259-dm.c
 ===================================================================
---- ioemu.orig/target-i386-dm/i8259-dm.c       2006-12-20 15:04:54.000000000 +0000
-+++ ioemu/target-i386-dm/i8259-dm.c    2006-12-20 15:04:55.000000000 +0000
+--- ioemu.orig/target-i386-dm/i8259-dm.c       2007-05-09 13:56:35.000000000 +0100
++++ ioemu/target-i386-dm/i8259-dm.c    2007-05-09 13:56:55.000000000 +0100
 @@ -33,7 +33,7 @@
  
  void pic_set_irq_new(void *opaque, int irq, int level)
@@ -56,8 +56,8 @@ Index: ioemu/target-i386-dm/i8259-dm.c
 Index: ioemu/target-i386-dm/piix_pci-dm.c
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ ioemu/target-i386-dm/piix_pci-dm.c 2006-12-20 15:08:13.000000000 +0000
-@@ -0,0 +1,397 @@
++++ ioemu/target-i386-dm/piix_pci-dm.c 2007-05-09 14:07:46.000000000 +0100
+@@ -0,0 +1,447 @@
 +/*
 + * QEMU i440FX/PIIX3 PCI Bridge Emulation
 + *
@@ -100,20 +100,60 @@ Index: ioemu/target-i386-dm/piix_pci-dm.c
 +    return s->config_reg;
 +}
 +
-+static void i440fx_set_irq(PCIDevice *pci_dev, void *pic, int intx, int level)
++/* return the global irq number corresponding to a given device irq
++   pin. We could also use the bus number to have a more precise
++   mapping. */
++static int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
++{
++#ifndef CONFIG_DM
++    int slot_addend;
++    slot_addend = (pci_dev->devfn >> 3) - 1;
++    return (irq_num + slot_addend) & 3;
++#else  /* !CONFIG_DM */
++    return irq_num + ((pci_dev->devfn >> 3) << 2);
++#endif /* !CONFIG_DM */
++}
++
++static void i440fx_set_irq(void *pic, int irq_num, int level)
 +{
-+    xc_hvm_set_pci_intx_level(xc_handle, domid, 0, 0, pci_dev->devfn >> 3,
-+                              intx, level);
++    xc_hvm_set_pci_intx_level(xc_handle, domid, 0, 0, irq_num >> 2,
++                              irq_num & 3, level);
 +}
 +
-+PCIBus *i440fx_init(void)
++static void i440fx_save(QEMUFile* f, void *opaque)
++{
++    PCIDevice *d = opaque;
++    pci_device_save(d, f);
++#ifndef CONFIG_DM
++    qemu_put_8s(f, &smm_enabled);
++#endif /* !CONFIG_DM */
++}
++
++static int i440fx_load(QEMUFile* f, void *opaque, int version_id)
++{
++    PCIDevice *d = opaque;
++    int ret;
++
++    if (version_id != 1)
++        return -EINVAL;
++    ret = pci_device_load(d, f);
++    if (ret < 0)
++        return ret;
++#ifndef CONFIG_DM
++    i440fx_update_memory_mappings(d);
++    qemu_get_8s(f, &smm_enabled);
++#endif /* !CONFIG_DM */
++    return 0;
++}
++
++PCIBus *i440fx_init(PCIDevice **pi440fx_state)
 +{
 +    PCIBus *b;
 +    PCIDevice *d;
 +    I440FXState *s;
 +
 +    s = qemu_mallocz(sizeof(I440FXState));
-+    b = pci_register_bus(i440fx_set_irq, NULL, 0);
++    b = pci_register_bus(i440fx_set_irq, pci_slot_get_pirq, NULL, 0, 128);
 +    s->bus = b;
 +
 +    register_ioport_write(0xcf8, 4, 4, i440fx_addr_writel, s);
@@ -137,6 +177,9 @@ Index: ioemu/target-i386-dm/piix_pci-dm.c
 +    d->config[0x0a] = 0x00; // class_sub = host2pci
 +    d->config[0x0b] = 0x06; // class_base = PCI_bridge
 +    d->config[0x0e] = 0x00; // header_type
++
++    register_savevm("I440FX", 0, 1, i440fx_save, i440fx_load, d);
++    *pi440fx_state = d;
 +    return b;
 +}
 +
@@ -144,12 +187,6 @@ Index: ioemu/target-i386-dm/piix_pci-dm.c
 +
 +static PCIDevice *piix3_dev;
 +
-+static int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
-+{
-+    /* This is the barber's pole mapping used by Xen. */
-+    return (irq_num + (pci_dev->devfn >> 3)) & 3;
-+}
-+
 +static void piix3_write_config(PCIDevice *d, 
 +                               uint32_t address, uint32_t val, int len)
 +{
@@ -193,7 +230,6 @@ Index: ioemu/target-i386-dm/piix_pci-dm.c
 +    pci_conf[0x80] = 0x00;
 +    pci_conf[0x82] = 0x00;
 +    pci_conf[0xa0] = 0x08;
-+    pci_conf[0xa0] = 0x08;
 +    pci_conf[0xa2] = 0x00;
 +    pci_conf[0xa3] = 0x00;
 +    pci_conf[0xa4] = 0x00;
@@ -207,14 +243,28 @@ Index: ioemu/target-i386-dm/piix_pci-dm.c
 +    pci_conf[0xae] = 0x00;
 +}
 +
-+int piix3_init(PCIBus *bus)
++static void piix_save(QEMUFile* f, void *opaque)
++{
++    PCIDevice *d = opaque;
++    pci_device_save(d, f);
++}
++
++static int piix_load(QEMUFile* f, void *opaque, int version_id)
++{
++    PCIDevice *d = opaque;
++    if (version_id != 2)
++        return -EINVAL;
++    return pci_device_load(d, f);
++}
++
++int piix3_init(PCIBus *bus, int devfn)
 +{
 +    PCIDevice *d;
 +    uint8_t *pci_conf;
 +
 +    d = pci_register_device(bus, "PIIX3", sizeof(PCIDevice),
-+                                    -1, NULL, piix3_write_config);
-+    register_savevm("PIIX3", 0, 1, generic_pci_save, generic_pci_load, d);
++                                    devfn, NULL, piix3_write_config);
++    register_savevm("PIIX3", 0, 2, piix_save, piix_load, d);
 +
 +    piix3_dev = d;
 +    pci_conf = d->config;
index 6d934fe3f75b07408fb498afb6a2ac59ec3b015a..a4bb19b186685bf517e1f7aafdfa81edd998e6d6 100644 (file)
@@ -1,8 +1,8 @@
 Index: ioemu/hw/vga.c
 ===================================================================
---- ioemu.orig/hw/vga.c        2006-09-21 19:07:52.000000000 +0100
-+++ ioemu/hw/vga.c     2006-09-21 19:08:09.000000000 +0100
-@@ -1463,14 +1463,15 @@
+--- ioemu.orig/hw/vga.c        2007-05-03 19:15:57.000000000 +0100
++++ ioemu/hw/vga.c     2007-05-03 19:46:13.000000000 +0100
+@@ -1477,14 +1477,15 @@
   */
  static void vga_draw_graphic(VGAState *s, int full_update)
  {
@@ -20,7 +20,7 @@ Index: ioemu/hw/vga.c
      full_update |= update_basic_params(s);
  
      s->get_resolution(s, &width, &height);
-@@ -1561,8 +1562,8 @@
+@@ -1575,8 +1576,8 @@
      addr1 = (s->start_addr * 4);
      bwidth = width * 4;
      y_start = -1;
@@ -31,7 +31,7 @@ Index: ioemu/hw/vga.c
      d = s->ds->data;
      linesize = s->ds->linesize;
      y1 = 0;
-@@ -1592,9 +1593,9 @@
+@@ -1606,9 +1607,9 @@
          if (update) {
              if (y_start < 0)
                  y_start = y;
index c8e178a3d7cc817e697a77ae8b05f8f0ebbfafd7..3cd26c49de7f3c23c57ad12a65ef4acbb1bfdb37 100644 (file)
@@ -1,20 +1,20 @@
 Index: ioemu/Makefile.target
 ===================================================================
---- ioemu.orig/Makefile.target 2007-05-03 10:07:52.000000000 +0100
-+++ ioemu/Makefile.target      2007-05-03 10:07:53.000000000 +0100
-@@ -355,7 +355,7 @@
+--- ioemu.orig/Makefile.target 2007-05-03 19:09:54.000000000 +0100
++++ ioemu/Makefile.target      2007-05-03 19:15:05.000000000 +0100
+@@ -386,7 +386,7 @@
  ifeq ($(TARGET_BASE_ARCH), i386)
  # Hardware support
  VL_OBJS+= ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
 -VL_OBJS+= fdc.o mc146818rtc.o serial.o i8254.o pcspk.o pc.o
 +VL_OBJS+= fdc.o mc146818rtc.o serial.o pc.o
  VL_OBJS+= cirrus_vga.o mixeng.o parallel.o acpi.o piix_pci.o
- VL_OBJS+= usb-uhci.o
DEFINES += -DHAS_AUDIO
+ VL_OBJS+= usb-uhci.o smbus_eeprom.o
CPPFLAGS += -DHAS_AUDIO
 Index: ioemu/hw/pc.c
 ===================================================================
---- ioemu.orig/hw/pc.c 2007-05-03 10:07:52.000000000 +0100
-+++ ioemu/hw/pc.c      2007-05-03 10:07:53.000000000 +0100
+--- ioemu.orig/hw/pc.c 2007-05-03 19:11:08.000000000 +0100
++++ ioemu/hw/pc.c      2007-05-03 19:15:05.000000000 +0100
 @@ -38,7 +38,9 @@
  
  static fdctrl_t *floppy_controller;
@@ -25,7 +25,7 @@ Index: ioemu/hw/pc.c
  #ifndef CONFIG_DM
  static IOAPICState *ioapic;
  #endif /* !CONFIG_DM */
-@@ -810,8 +812,10 @@
+@@ -664,8 +666,10 @@
      }
  #endif /* !CONFIG_DM */
      isa_pic = pic_init(pic_irq_request, first_cpu);
@@ -38,9 +38,9 @@ Index: ioemu/hw/pc.c
          pic_set_alt_irq_func(isa_pic, ioapic_set_irq, ioapic);
 Index: ioemu/vl.c
 ===================================================================
---- ioemu.orig/vl.c    2007-05-03 10:07:53.000000000 +0100
-+++ ioemu/vl.c 2007-05-03 10:07:53.000000000 +0100
-@@ -5622,6 +5622,7 @@
+--- ioemu.orig/vl.c    2007-05-03 19:14:57.000000000 +0100
++++ ioemu/vl.c 2007-05-03 19:15:05.000000000 +0100
+@@ -6537,6 +6537,7 @@
  
  #ifdef HAS_AUDIO
  struct soundhw soundhw[] = {
@@ -48,7 +48,7 @@ Index: ioemu/vl.c
  #ifdef TARGET_I386
      {
          "pcspk",
-@@ -5631,6 +5632,7 @@
+@@ -6546,6 +6547,7 @@
          { .init_isa = pcspk_audio_init }
      },
  #endif
index a3357ea9bd3cfd9dc86d863459a5cd734674327a..4df37e5dc4e67c57bd07b1e0a2d007a32a8c7a43 100644 (file)
@@ -7,9 +7,9 @@ Signed-off-by: Xiaowei Yang <xiaowei.yang@intel.com>
 
 Index: ioemu/Makefile.target
 ===================================================================
---- ioemu.orig/Makefile.target 2006-12-08 01:41:15.000000000 +0000
-+++ ioemu/Makefile.target      2006-12-08 01:41:15.000000000 +0000
-@@ -295,7 +295,11 @@
+--- ioemu.orig/Makefile.target 2007-05-09 14:12:44.000000000 +0100
++++ ioemu/Makefile.target      2007-05-09 14:14:08.000000000 +0100
+@@ -324,7 +324,11 @@
  endif
  
  # qemu-dm objects
@@ -21,7 +21,7 @@ Index: ioemu/Makefile.target
  
  all: $(PROGS)
  
-@@ -355,7 +359,11 @@
+@@ -386,7 +390,11 @@
  ifeq ($(TARGET_BASE_ARCH), i386)
  # Hardware support
  VL_OBJS+= ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
@@ -31,13 +31,13 @@ Index: ioemu/Makefile.target
 +VL_OBJS+= fdc.o serial.o pc.o
 +endif
  VL_OBJS+= cirrus_vga.o mixeng.o parallel.o acpi.o piix_pci.o
- VL_OBJS+= usb-uhci.o
+ VL_OBJS+= usb-uhci.o smbus_eeprom.o
  VL_OBJS+= piix4acpi.o
 Index: ioemu/target-i386-dm/rtc-dm.c
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ ioemu/target-i386-dm/rtc-dm.c      2006-12-08 01:41:15.000000000 +0000
-@@ -0,0 +1,107 @@
++++ ioemu/target-i386-dm/rtc-dm.c      2007-05-09 14:14:13.000000000 +0100
+@@ -0,0 +1,124 @@
 +/*
 + * QEMU MC146818 RTC emulation
 + * 
@@ -64,13 +64,18 @@ Index: ioemu/target-i386-dm/rtc-dm.c
 +
 +#include "vl.h"
 +
-+//#define DEBUG_CMOS
++// #define DEBUG_CMOS
 +
 +struct RTCState {
 +    uint8_t cmos_data[128];
 +    uint8_t cmos_index;
 +};
 +
++static inline int to_bcd(RTCState *s, int a)
++{
++    return ((a / 10) << 4) | (a % 10);
++}
++
 +void rtc_set_memory(RTCState *s, int addr, int val)
 +{
 +    if (addr >= 0 && addr <= 127)
@@ -132,11 +137,23 @@ Index: ioemu/target-i386-dm/rtc-dm.c
 +RTCState *rtc_init(int base, int irq)
 +{
 +    RTCState *s;
++    time_t ti;
++    struct tm *tm;
++    int val;
 +
 +    s = qemu_mallocz(sizeof(RTCState));
 +    if (!s)
 +        return NULL;
 +
++/* PC cmos mappings */
++#define REG_IBM_CENTURY_BYTE        0x32
++#define REG_IBM_PS2_CENTURY_BYTE    0x37
++    time(&ti);
++    tm = gmtime(&ti);         /* XXX localtime and update from guest? */
++    val = to_bcd(s, (tm->tm_year / 100) + 19);
++    rtc_set_memory(s, REG_IBM_CENTURY_BYTE, val);
++    rtc_set_memory(s, REG_IBM_PS2_CENTURY_BYTE, val);
++
 +    register_ioport_write(base, 2, 1, cmos_ioport_write, s);
 +    register_ioport_read(base, 2, 1, cmos_ioport_read, s);
 +
index 869842fc3f330faf8612ad367824d70ba8e8809b..cb5ecaf6ea2d7abe96abc8497bc679f0735d9ce1 100644 (file)
@@ -33,9 +33,9 @@ Signed-off-by: Keir Fraser <keir@xensource.com>
 
 Index: ioemu/hw/ide.c
 ===================================================================
---- ioemu.orig/hw/ide.c        2007-05-03 15:07:16.000000000 +0100
-+++ ioemu/hw/ide.c     2007-05-03 15:07:17.000000000 +0100
-@@ -838,7 +838,7 @@
+--- ioemu.orig/hw/ide.c        2007-05-03 20:38:33.000000000 +0100
++++ ioemu/hw/ide.c     2007-05-03 20:45:33.000000000 +0100
+@@ -767,7 +767,7 @@
  static void ide_sector_read(IDEState *s)
  {
      int64_t sector_num;
@@ -44,7 +44,7 @@ Index: ioemu/hw/ide.c
  
      s->status = READY_STAT | SEEK_STAT;
      s->error = 0; /* not needed by IDE spec, but needed by Windows */
-@@ -853,7 +853,11 @@
+@@ -782,7 +782,11 @@
  #endif
          if (n > s->req_nb_sectors)
              n = s->req_nb_sectors;
@@ -57,20 +57,7 @@ Index: ioemu/hw/ide.c
          ide_transfer_start(s, s->io_buffer, 512 * n, ide_sector_read);
          ide_set_irq(s);
          ide_set_sector(s, sector_num + n);
-@@ -879,7 +883,11 @@
-             if (n > MAX_MULT_SECTORS)
-                 n = MAX_MULT_SECTORS;
-             sector_num = ide_get_sector(s);
--            bdrv_read(s->bs, sector_num, s->io_buffer, n);
-+            if (bdrv_read(s->bs, sector_num, s->io_buffer, n) != 0) {
-+                ide_abort_command(s);
-+                ide_set_irq(s);
-+                return 0;
-+            }
-             s->io_buffer_index = 0;
-             s->io_buffer_size = n * 512;
-             len = s->io_buffer_size;
-@@ -925,7 +933,7 @@
+@@ -899,7 +903,7 @@
  static void ide_sector_write(IDEState *s)
  {
      int64_t sector_num;
@@ -79,7 +66,7 @@ Index: ioemu/hw/ide.c
  
      s->status = READY_STAT | SEEK_STAT;
      sector_num = ide_get_sector(s);
-@@ -935,7 +943,11 @@
+@@ -909,7 +913,11 @@
      n = s->nsector;
      if (n > s->req_nb_sectors)
          n = s->req_nb_sectors;
@@ -92,19 +79,3 @@ Index: ioemu/hw/ide.c
      s->nsector -= n;
      if (s->nsector == 0) {
          /* no more sector to write */
-@@ -981,8 +993,13 @@
-         if (len == 0) {
-             n = s->io_buffer_size >> 9;
-             sector_num = ide_get_sector(s);
--            bdrv_write(s->bs, sector_num, s->io_buffer, 
--                       s->io_buffer_size >> 9);
-+            if (bdrv_write(s->bs, sector_num, s->io_buffer, 
-+                         s->io_buffer_size >> 9) != 0) {
-+                ide_abort_command(s);
-+                ide_set_irq(s);
-+                return 0;
-+            }
-+
-             sector_num += n;
-             ide_set_sector(s, sector_num);
-             s->nsector -= n;
index bfa77e719aba80cf11ba1da99fd8e342a22d8728..46082da7c959984d481863f821935221b2b56f69 100644 (file)
@@ -1,8 +1,8 @@
 Index: ioemu/vl.c
 ===================================================================
---- ioemu.orig/vl.c    2007-05-03 15:07:15.000000000 +0100
-+++ ioemu/vl.c 2007-05-03 15:07:15.000000000 +0100
-@@ -5924,6 +5924,7 @@
+--- ioemu.orig/vl.c    2007-05-09 13:47:16.000000000 +0100
++++ ioemu/vl.c 2007-05-09 13:47:16.000000000 +0100
+@@ -6839,6 +6839,7 @@
      unsigned long ioreq_pfn;
      extern void *shared_page;
      extern void *buffered_io_page;
@@ -10,7 +10,7 @@ Index: ioemu/vl.c
      unsigned long nr_pages;
  
      char qemu_dm_logfilename[64];
-@@ -6530,6 +6531,10 @@
+@@ -7544,6 +7545,10 @@
                                         PROT_READ|PROT_WRITE,
                                         BUFFER_IO_PAGE_START >> PAGE_SHIFT);
  
@@ -23,11 +23,11 @@ Index: ioemu/vl.c
        
 Index: ioemu/hw/ide.c
 ===================================================================
---- ioemu.orig/hw/ide.c        2007-05-03 15:07:15.000000000 +0100
-+++ ioemu/hw/ide.c     2007-05-03 15:07:15.000000000 +0100
-@@ -474,6 +474,121 @@
- }
- #endif /* DMA_MULTI_THREAD */
+--- ioemu.orig/hw/ide.c        2007-05-09 13:47:15.000000000 +0100
++++ ioemu/hw/ide.c     2007-05-09 13:47:16.000000000 +0100
+@@ -393,6 +393,121 @@
+     int type; /* see IDE_TYPE_xxx */
+ } PCIIDEState;
  
 +#if defined(__ia64__)
 +#include <xen/hvm/ioreq.h>
@@ -144,10 +144,10 @@ Index: ioemu/hw/ide.c
 +#define buffered_pio_read(I,A,S)    do {} while (0)
 +#endif
 +
- static void ide_dma_start(IDEState *s, IDEDMAFunc *dma_cb);
+ static void ide_dma_start(IDEState *s, BlockDriverCompletionFunc *dma_cb);
+ static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret);
  
- static void padstr(char *str, const char *src, int len)
-@@ -658,6 +773,7 @@
+@@ -587,6 +702,7 @@
      s->data_ptr = buf;
      s->data_end = buf + size;
      s->status |= DRQ_STAT;
@@ -155,7 +155,7 @@ Index: ioemu/hw/ide.c
  }
  
  static void ide_transfer_stop(IDEState *s)
-@@ -666,6 +782,7 @@
+@@ -595,6 +711,7 @@
      s->data_ptr = s->io_buffer;
      s->data_end = s->io_buffer;
      s->status &= ~DRQ_STAT;
@@ -163,7 +163,7 @@ Index: ioemu/hw/ide.c
  }
  
  static int64_t ide_get_sector(IDEState *s)
-@@ -1578,6 +1695,7 @@
+@@ -1596,6 +1713,7 @@
          ide_if[0].select = (val & ~0x10) | 0xa0;
          ide_if[1].select = (val | 0x10) | 0xa0;
          /* select drive */
@@ -171,7 +171,7 @@ Index: ioemu/hw/ide.c
          unit = (val >> 4) & 1;
          s = ide_if + unit;
          ide_if->cur_drive = s;
-@@ -1936,6 +2054,7 @@
+@@ -1954,6 +2072,7 @@
      IDEState *s = ((IDEState *)opaque)->cur_drive;
      uint8_t *p;
  
@@ -179,7 +179,7 @@ Index: ioemu/hw/ide.c
      p = s->data_ptr;
      *(uint16_t *)p = le16_to_cpu(val);
      p += 2;
-@@ -1949,6 +2068,8 @@
+@@ -1967,6 +2086,8 @@
      IDEState *s = ((IDEState *)opaque)->cur_drive;
      uint8_t *p;
      int ret;
@@ -188,7 +188,7 @@ Index: ioemu/hw/ide.c
      p = s->data_ptr;
      ret = cpu_to_le16(*(uint16_t *)p);
      p += 2;
-@@ -1963,6 +2084,7 @@
+@@ -1981,6 +2102,7 @@
      IDEState *s = ((IDEState *)opaque)->cur_drive;
      uint8_t *p;
  
@@ -196,7 +196,7 @@ Index: ioemu/hw/ide.c
      p = s->data_ptr;
      *(uint32_t *)p = le32_to_cpu(val);
      p += 4;
-@@ -1977,6 +2099,7 @@
+@@ -1995,6 +2117,7 @@
      uint8_t *p;
      int ret;
      
@@ -204,12 +204,21 @@ Index: ioemu/hw/ide.c
      p = s->data_ptr;
      ret = cpu_to_le32(*(uint32_t *)p);
      p += 4;
-@@ -2634,6 +2757,8 @@
+@@ -2624,6 +2747,8 @@
+     ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6);
+     ide_init_ioport(&d->ide_if[2], 0x170, 0x376);
++    buffered_pio_init();
++
+     register_savevm("ide", 0, 1, pci_ide_save, pci_ide_load, d);
+ }
+@@ -2663,6 +2788,8 @@
      ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6);
      ide_init_ioport(&d->ide_if[2], 0x170, 0x376);
  
 +    buffered_pio_init();
 +
-     register_savevm("ide_pci", 0, 1, generic_pci_save, generic_pci_load, d);
      register_savevm("ide", 0, 1, pci_ide_save, pci_ide_load, d);
+ }
  
index 3ca3a855525ce47ad1fd66fc188700a3216e43c3..5b78873b3655eec527875017845f0be0b6675262 100644 (file)
@@ -1,7 +1,7 @@
 Index: ioemu/hw/iommu.c
 ===================================================================
---- ioemu.orig/hw/iommu.c      2007-05-03 09:56:32.000000000 +0100
-+++ ioemu/hw/iommu.c   2007-05-03 10:05:51.000000000 +0100
+--- ioemu.orig/hw/iommu.c      2007-05-03 18:18:01.000000000 +0100
++++ ioemu/hw/iommu.c   2007-05-03 19:09:15.000000000 +0100
 @@ -82,7 +82,11 @@
  #define IOPTE_VALID         0x00000002 /* IOPTE is valid */
  #define IOPTE_WAZ           0x00000001 /* Write as zeros */
@@ -16,9 +16,9 @@ Index: ioemu/hw/iommu.c
  
 Index: ioemu/cpu-all.h
 ===================================================================
---- ioemu.orig/cpu-all.h       2007-05-03 09:56:32.000000000 +0100
-+++ ioemu/cpu-all.h    2007-05-03 10:05:51.000000000 +0100
-@@ -835,6 +835,31 @@
+--- ioemu.orig/cpu-all.h       2007-05-03 19:00:55.000000000 +0100
++++ ioemu/cpu-all.h    2007-05-03 19:09:15.000000000 +0100
+@@ -843,6 +843,31 @@
                  :"=m" (*(volatile long *)addr)
                  :"dIr" (nr));
  }
@@ -52,11 +52,11 @@ Index: ioemu/cpu-all.h
  /* memory API */
 Index: ioemu/vl.c
 ===================================================================
---- ioemu.orig/vl.c    2007-05-03 10:04:06.000000000 +0100
-+++ ioemu/vl.c 2007-05-03 10:25:23.000000000 +0100
-@@ -6142,6 +6142,11 @@
-             exit(1);
+--- ioemu.orig/vl.c    2007-05-03 19:08:57.000000000 +0100
++++ ioemu/vl.c 2007-05-03 19:09:15.000000000 +0100
+@@ -7149,6 +7149,11 @@
      }
+ #endif
  
 +#if defined (__ia64__)
 +    if (ram_size > MMIO_START)
@@ -66,7 +66,7 @@ Index: ioemu/vl.c
      /* init the memory */
      phys_ram_size = ram_size + vga_ram_size + bios_size;
  
-@@ -6182,6 +6187,44 @@
+@@ -7198,6 +7203,44 @@
  
      free(page_array);
  
@@ -113,9 +113,9 @@ Index: ioemu/vl.c
      phys_ram_base = qemu_vmalloc(phys_ram_size);
 Index: ioemu/exec-all.h
 ===================================================================
---- ioemu.orig/exec-all.h      2007-05-03 09:56:32.000000000 +0100
-+++ ioemu/exec-all.h   2007-05-03 10:05:51.000000000 +0100
-@@ -462,12 +462,13 @@
+--- ioemu.orig/exec-all.h      2007-05-03 18:38:09.000000000 +0100
++++ ioemu/exec-all.h   2007-05-03 19:09:15.000000000 +0100
+@@ -472,12 +472,13 @@
  }
  #endif
  
@@ -134,8 +134,8 @@ Index: ioemu/exec-all.h
  
 Index: ioemu/target-i386-dm/cpu.h
 ===================================================================
---- ioemu.orig/target-i386-dm/cpu.h    2007-05-03 09:56:32.000000000 +0100
-+++ ioemu/target-i386-dm/cpu.h 2007-05-03 10:25:13.000000000 +0100
+--- ioemu.orig/target-i386-dm/cpu.h    2007-05-03 18:49:10.000000000 +0100
++++ ioemu/target-i386-dm/cpu.h 2007-05-03 19:09:15.000000000 +0100
 @@ -78,7 +78,11 @@
  /* helper2.c */
  int main_loop(void);
@@ -151,7 +151,7 @@ Index: ioemu/target-i386-dm/cpu.h
 Index: ioemu/ia64_intrinsic.h
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ ioemu/ia64_intrinsic.h     2007-05-03 10:05:51.000000000 +0100
++++ ioemu/ia64_intrinsic.h     2007-05-03 19:09:15.000000000 +0100
 @@ -0,0 +1,276 @@
 +#ifndef IA64_INTRINSIC_H
 +#define IA64_INTRINSIC_H
index 5a2dd519a4f9f1cecb00665884b22fb11aae1bf4..7978b532713e026467138a441078a6c1665577bb 100644 (file)
@@ -1,8 +1,8 @@
 Index: ioemu/hw/cirrus_vga.c
 ===================================================================
---- ioemu.orig/hw/cirrus_vga.c 2007-05-03 15:03:18.000000000 +0100
-+++ ioemu/hw/cirrus_vga.c      2007-05-03 15:08:02.000000000 +0100
-@@ -3011,11 +3011,42 @@
+--- ioemu.orig/hw/cirrus_vga.c 2007-05-09 14:09:12.000000000 +0100
++++ ioemu/hw/cirrus_vga.c      2007-05-09 14:10:58.000000000 +0100
+@@ -3016,11 +3016,42 @@
      cirrus_mmio_writel,
  };
  
@@ -43,9 +43,9 @@ Index: ioemu/hw/cirrus_vga.c
      CirrusVGAState *s = opaque;
 +    uint8_t vga_acc;
  
-     qemu_put_be32s(f, &s->latch);
-     qemu_put_8s(f, &s->sr_index);
-@@ -3050,11 +3081,20 @@
+     if (s->pci_dev)
+         pci_device_save(s->pci_dev, f);
+@@ -3058,11 +3089,20 @@
      qemu_put_be32s(f, &s->hw_cursor_y);
      /* XXX: we do not save the bitblt state - we assume we do not save
         the state when the blitter is active */
@@ -63,10 +63,10 @@ Index: ioemu/hw/cirrus_vga.c
  {
      CirrusVGAState *s = opaque;
 +    uint8_t vga_acc = 0;
+     int ret;
  
-     if (version_id != 1)
-         return -EINVAL;
-@@ -3093,6 +3133,14 @@
+     if (version_id > 2)
+@@ -3108,6 +3148,14 @@
      qemu_get_be32s(f, &s->hw_cursor_x);
      qemu_get_be32s(f, &s->hw_cursor_y);
  
@@ -81,32 +81,23 @@ Index: ioemu/hw/cirrus_vga.c
      /* force refresh */
      s->graphic_mode = -1;
      cirrus_update_bank_ptr(s, 0);
-@@ -3298,6 +3346,8 @@
-                     ds, vga_ram_base, vga_ram_offset, vga_ram_size);
-     cirrus_init_common(s, device_id, 1);
-+    register_savevm("cirrus_vga_pci", 0, 1, generic_pci_save, generic_pci_load, d);
-+
-     /* setup memory space */
-     /* memory #0 LFB */
-     /* memory #1 memory-mapped I/O */
 Index: ioemu/vl.c
 ===================================================================
---- ioemu.orig/vl.c    2007-05-03 15:03:18.000000000 +0100
-+++ ioemu/vl.c 2007-05-03 15:08:04.000000000 +0100
-@@ -4470,6 +4470,11 @@
-         qemu_fseek(f, cur_pos + record_len, SEEK_SET);
+--- ioemu.orig/vl.c    2007-05-09 14:09:12.000000000 +0100
++++ ioemu/vl.c 2007-05-09 14:10:50.000000000 +0100
+@@ -5025,6 +5025,11 @@
+     if (ret < 0) {
+         term_printf("Error %d while loading VM state\n", ret);
      }
-     fclose(f);
 +
 +    /* del tmp file */
-+    if (unlink(filename) == -1)
++    if (unlink(name) == -1)
 +        fprintf(stderr, "delete tmp qemu state file failed.\n");
 +
-     ret = 0;
   the_end:
      if (saved_vm_running)
-@@ -5056,6 +5061,7 @@
+         vm_start();
+@@ -5942,6 +5947,7 @@
  static QEMUResetEntry *first_reset_entry;
  int reset_requested;
  int shutdown_requested;
@@ -114,7 +105,7 @@ Index: ioemu/vl.c
  static int powerdown_requested;
  
  void qemu_register_reset(QEMUResetHandler *func, void *opaque)
-@@ -5816,6 +5822,15 @@
+@@ -6731,6 +6737,15 @@
      return 0;
  }
  
@@ -130,11 +121,10 @@ Index: ioemu/vl.c
  int main(int argc, char **argv)
  {
  #ifdef CONFIG_GDBSTUB
-@@ -6581,6 +6596,26 @@
-             vm_start();
-         }
+@@ -7625,6 +7640,25 @@
+       close(fd);
      }
-+
 +    /* register signal for the suspend request when save */
 +    {
 +        struct sigaction act;
@@ -157,44 +147,10 @@ Index: ioemu/vl.c
      main_loop();
      quit_timers();
      return 0;
-Index: ioemu/hw/pci.c
-===================================================================
---- ioemu.orig/hw/pci.c        2007-05-03 15:03:12.000000000 +0100
-+++ ioemu/hw/pci.c     2007-05-03 15:08:02.000000000 +0100
-@@ -40,6 +40,8 @@
- static int pci_irq_index;
- static PCIBus *first_bus;
-+static void pci_update_mappings(PCIDevice *d);
-+
- PCIBus *pci_register_bus(pci_set_irq_fn set_irq, void *pic, int devfn_min)
- {
-     PCIBus *bus;
-@@ -71,6 +73,7 @@
-         return -EINVAL;
-     qemu_get_buffer(f, s->config, 256);
-+    pci_update_mappings(s);
-     return 0;
- }
-Index: ioemu/hw/ide.c
-===================================================================
---- ioemu.orig/hw/ide.c        2007-05-03 15:03:12.000000000 +0100
-+++ ioemu/hw/ide.c     2007-05-03 15:08:04.000000000 +0100
-@@ -2405,6 +2405,8 @@
-               pic_set_irq_new, isa_pic, 15);
-     ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6);
-     ide_init_ioport(&d->ide_if[2], 0x170, 0x376);
-+
-+    register_savevm("ide_pci", 0, 1, generic_pci_save, generic_pci_load, d);
- }
- /***********************************************************/
 Index: ioemu/target-i386-dm/helper2.c
 ===================================================================
---- ioemu.orig/target-i386-dm/helper2.c        2007-05-03 15:03:18.000000000 +0100
-+++ ioemu/target-i386-dm/helper2.c     2007-05-03 15:09:10.000000000 +0100
+--- ioemu.orig/target-i386-dm/helper2.c        2007-05-09 14:09:11.000000000 +0100
++++ ioemu/target-i386-dm/helper2.c     2007-05-09 14:10:49.000000000 +0100
 @@ -540,8 +540,10 @@
  {
      extern int vm_running;
@@ -206,7 +162,7 @@ Index: ioemu/target-i386-dm/helper2.c
  
      qemu_set_fd_handler(evtchn_fd, cpu_handle_ioreq, NULL, env);
  
-@@ -549,7 +551,15 @@
+@@ -549,7 +551,14 @@
          /* Wait up to 10 msec. */
          main_loop_wait(10);
  
@@ -218,8 +174,7 @@ Index: ioemu/target-i386-dm/helper2.c
 +
 +    /* Save the device state */
 +    sprintf(qemu_file, "/tmp/xen.qemu-dm.%d", domid);
-+    if (qemu_savevm(qemu_file) < 0)
-+        fprintf(stderr, "qemu save fail.\n");
++    do_savevm(qemu_file);
  
      return 0;
  }
index 204cabadc7240df4fcea339836d146c899281c7f..b367c5656c389ad8da8c81abd19c3b8b8a377598 100644 (file)
@@ -1,34 +1,38 @@
 Index: ioemu/hw/piix4acpi.c
 ===================================================================
---- ioemu.orig/hw/piix4acpi.c  2007-05-03 15:07:43.000000000 +0100
-+++ ioemu/hw/piix4acpi.c       2007-05-03 15:07:43.000000000 +0100
-@@ -57,6 +57,20 @@
+--- ioemu.orig/hw/piix4acpi.c  2007-05-09 13:54:28.000000000 +0100
++++ ioemu/hw/piix4acpi.c       2007-05-09 13:54:41.000000000 +0100
+@@ -57,6 +57,26 @@
      uint16_t pm1_control; /* pm1a_ECNT_BLK */
  } PCIAcpiState;
  
 +static void piix4acpi_save(QEMUFile *f, void *opaque)
 +{
 +    PCIAcpiState *s = opaque;
++    pci_device_save(&s->dev, f);
 +    qemu_put_be16s(f, &s->pm1_control);
 +}
 +
 +static int piix4acpi_load(QEMUFile *f, void *opaque, int version_id)
 +{
 +    PCIAcpiState *s = opaque;
++    int ret;
 +    if (version_id > 1) 
 +        return -EINVAL;
++    ret = pci_device_load(&s->dev, f);
++    if (ret < 0)
++      return ret;
 +    qemu_get_be16s(f, &s->pm1_control);
++    return 0;
 +}
 +
  static void acpiPm1Control_writeb(void *opaque, uint32_t addr, uint32_t val)
  {
      PCIAcpiState *s = opaque;
-@@ -193,4 +207,8 @@
+@@ -193,4 +213,6 @@
      d->pm1_control = SCI_EN;
  
-     acpi_map(d, 0, 0x1f40, 0x10, PCI_ADDRESS_SPACE_IO);
+     acpi_map((PCIDevice *)d, 0, 0x1f40, 0x10, PCI_ADDRESS_SPACE_IO);
 +
-+    register_savevm("piix4acpi", 0, 1, piix4acpi_save, piix4acpi_load, d);    
-+    register_savevm("piix4acpi_pci", 0, 1, generic_pci_save, generic_pci_load, 
-+                    &d->dev);
++    register_savevm("piix4acpi", 0, 1, piix4acpi_save, piix4acpi_load, d);
  }
index 3298d9d535aa9d70c09198de8d7279d74d57867e..1177091ac5336418523c1cb40325c8f7c1fd3b30 100644 (file)
@@ -1,9 +1,13 @@
 Index: ioemu/hw/ide.c
 ===================================================================
---- ioemu.orig/hw/ide.c        2007-05-02 14:12:00.000000000 +0100
-+++ ioemu/hw/ide.c     2007-05-02 14:12:40.000000000 +0100
-@@ -2372,6 +2372,120 @@
-               cmd646_set_irq, d, 1);
+--- ioemu.orig/hw/ide.c        2007-05-03 19:24:12.000000000 +0100
++++ ioemu/hw/ide.c     2007-05-03 19:24:43.000000000 +0100
+@@ -2623,9 +2623,124 @@
+     ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6);
+     ide_init_ioport(&d->ide_if[2], 0x170, 0x376);
++    register_savevm("ide_pci", 0, 1, pci_device_save, pci_device_load, d);
+     register_savevm("ide", 0, 1, pci_ide_save, pci_ide_load, d);
  }
  
 +static void pci_ide_save(QEMUFile* f, void *opaque)
@@ -123,11 +127,11 @@ Index: ioemu/hw/ide.c
  /* hd_table must contain 4 block drivers */
  /* NOTE: for the PIIX3, the IRQs and IOports are hardcoded */
  void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn)
-@@ -2407,6 +2521,7 @@
+@@ -2662,6 +2777,7 @@
+     ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6);
      ide_init_ioport(&d->ide_if[2], 0x170, 0x376);
  
-     register_savevm("ide_pci", 0, 1, generic_pci_save, generic_pci_load, d);
-+    register_savevm("ide", 0, 1, pci_ide_save, pci_ide_load, d);
++    register_savevm("ide_pci", 0, 1, pci_device_save, pci_device_load, d);
+     register_savevm("ide", 0, 1, pci_ide_save, pci_ide_load, d);
  }
  
- /***********************************************************/
index 91e4ad7f4954c127441f2f376ac63e5ae2d0364c..627629051e03234a6121d0a87ef0a177b3f795db 100644 (file)
@@ -1,7 +1,7 @@
 Index: ioemu/xenstore.c
 ===================================================================
---- ioemu.orig/xenstore.c      2007-05-03 10:42:11.000000000 +0100
-+++ ioemu/xenstore.c   2007-05-03 14:17:13.000000000 +0100
+--- ioemu.orig/xenstore.c      2007-05-03 20:38:53.000000000 +0100
++++ ioemu/xenstore.c   2007-05-03 20:49:57.000000000 +0100
 @@ -11,6 +11,11 @@
  #include "vl.h"
  #include "block_int.h"
@@ -15,7 +15,7 @@ Index: ioemu/xenstore.c
  static struct xs_handle *xsh = NULL;
  static char *media_filename[MAX_DISKS];
 @@ -173,6 +178,13 @@
-       }
+         }
      }
  
 +    /* Set a watch for log-dirty requests from the migration tools */
@@ -143,7 +143,7 @@ Index: ioemu/xenstore.c
      char **vec, *image = NULL;
 @@ -200,6 +318,11 @@
      if (!vec)
-       return;
+         return;
  
 +    if (!strcmp(vec[XS_WATCH_TOKEN], "logdirty")) {
 +        xenstore_process_logdirty_event();
@@ -151,12 +151,12 @@ Index: ioemu/xenstore.c
 +    }
 +
      if (strncmp(vec[XS_WATCH_TOKEN], "hd", 2) ||
-       strlen(vec[XS_WATCH_TOKEN]) != 3)
-       goto out;
+         strlen(vec[XS_WATCH_TOKEN]) != 3)
+         goto out;
 Index: ioemu/target-i386-dm/exec-dm.c
 ===================================================================
---- ioemu.orig/target-i386-dm/exec-dm.c        2007-05-03 14:13:38.000000000 +0100
-+++ ioemu/target-i386-dm/exec-dm.c     2007-05-03 14:18:14.000000000 +0100
+--- ioemu.orig/target-i386-dm/exec-dm.c        2007-05-03 20:49:54.000000000 +0100
++++ ioemu/target-i386-dm/exec-dm.c     2007-05-03 20:49:57.000000000 +0100
 @@ -431,6 +431,9 @@
  #define phys_ram_addr(x) ((addr < ram_size) ? (phys_ram_base + (x)) : NULL)
  #endif
index 0f77c741a5c96419246f2bab09b13d66d74a13df..d86058342d2aff6a8e2fbe7a698b9043c78f093d 100644 (file)
@@ -1,8 +1,8 @@
 Index: ioemu/hw/ne2000.c
 ===================================================================
---- ioemu.orig/hw/ne2000.c     2007-05-02 16:09:35.000000000 +0100
-+++ ioemu/hw/ne2000.c  2007-05-02 16:10:03.000000000 +0100
-@@ -739,7 +739,7 @@
+--- ioemu.orig/hw/ne2000.c     2007-05-09 13:47:48.000000000 +0100
++++ ioemu/hw/ne2000.c  2007-05-09 13:55:24.000000000 +0100
+@@ -750,7 +750,7 @@
               s->macaddr[4],
               s->macaddr[5]);
               
@@ -11,24 +11,3 @@ Index: ioemu/hw/ne2000.c
  }
  
  /***********************************************************/
-@@ -775,6 +775,7 @@
-     PCINE2000State *d;
-     NE2000State *s;
-     uint8_t *pci_conf;
-+    int instance;
-     
-     d = (PCINE2000State *)pci_register_device(bus,
-                                               "NE2000", sizeof(PCINE2000State),
-@@ -809,8 +810,8 @@
-              s->macaddr[4],
-              s->macaddr[5]);
-              
--    /* XXX: instance number ? */
--    register_savevm("ne2000", 0, 2, ne2000_save, ne2000_load, s);
--    register_savevm("ne2000_pci", 0, 1, generic_pci_save, generic_pci_load, 
--                    &d->dev);
-+    instance = pci_bus_num(bus) << 8 | s->pci_dev->devfn;
-+    register_savevm("ne2000", instance, 2, ne2000_save, ne2000_load, s);
-+    register_savevm("ne2000_pci", instance, 1, generic_pci_save, 
-+                    generic_pci_load, &d->dev);
- }
index e29c1a10e4b9d1f889919f88a41d175d3273d8a5..835bb610c5eef59710e0ff823841b83ddcafc4da 100644 (file)
@@ -1,80 +1,32 @@
 Index: ioemu/hw/pcnet.c
 ===================================================================
---- ioemu.orig/hw/pcnet.c      2007-05-02 16:09:36.000000000 +0100
-+++ ioemu/hw/pcnet.c   2007-05-02 16:10:28.000000000 +0100
-@@ -1727,10 +1727,63 @@
-     cpu_register_physical_memory(addr, PCNET_PNPMMIO_SIZE, d->mmio_io_addr);
- }
+--- ioemu.orig/hw/pcnet.c      2007-05-09 13:47:20.000000000 +0100
++++ ioemu/hw/pcnet.c   2007-05-09 13:47:53.000000000 +0100
+@@ -1824,13 +1824,15 @@
  
-+
-+static void pcnet_save(QEMUFile *f, void *opaque)
-+{
-+    PCNetState *s = opaque;
-+    unsigned int i;
-+
-+    qemu_put_be32s(f, &s->rap);
-+    qemu_put_be32s(f, &s->isr);
-+    qemu_put_be32s(f, &s->lnkst);
-+    qemu_put_be32s(f, &s->rdra);
-+    qemu_put_be32s(f, &s->tdra);
-+    qemu_put_buffer(f, s->prom, 16);
-+    for (i = 0; i < 128; i++)
-+        qemu_put_be16s(f, &s->csr[i]);
-+    for (i = 0; i < 32; i++)
-+        qemu_put_be16s(f, &s->bcr[i]);
-+    qemu_put_be64s(f, &s->timer);
-+    qemu_put_be32s(f, &s->xmit_pos);
-+    qemu_put_be32s(f, &s->recv_pos);
-+    qemu_put_buffer(f, s->buffer, 4096);
-+    qemu_put_be32s(f, &s->tx_busy);
-+    qemu_put_timer(f, s->poll_timer);
-+}
-+
-+static int pcnet_load(QEMUFile *f, void *opaque, int version_id)
-+{
-+    PCNetState *s = opaque;
-+    int i, ret;
-+
-+    if (version_id != 1)
-+        return -EINVAL;
-+
-+    qemu_get_be32s(f, &s->rap);
-+    qemu_get_be32s(f, &s->isr);
-+    qemu_get_be32s(f, &s->lnkst);
-+    qemu_get_be32s(f, &s->rdra);
-+    qemu_get_be32s(f, &s->tdra);
-+    qemu_get_buffer(f, s->prom, 16);
-+    for (i = 0; i < 128; i++)
-+        qemu_get_be16s(f, &s->csr[i]);
-+    for (i = 0; i < 32; i++)
-+        qemu_get_be16s(f, &s->bcr[i]);
-+    qemu_get_be64s(f, &s->timer);
-+    qemu_get_be32s(f, &s->xmit_pos);
-+    qemu_get_be32s(f, &s->recv_pos);
-+    qemu_get_buffer(f, s->buffer, 4096);
-+    qemu_get_be32s(f, &s->tx_busy);
-+    qemu_get_timer(f, s->poll_timer);
-+
-+    return 0;
-+}
-+
- void pci_pcnet_init(PCIBus *bus, NICInfo *nd)
+ static void pcnet_common_init(PCNetState *d, NICInfo *nd, const char *info_str)
  {
-     PCNetState *d;
-     uint8_t *pci_conf;
 +    int instance;
++
+     d->poll_timer = qemu_new_timer(vm_clock, pcnet_poll_timer, d);
  
- #if 0
-     printf("sizeof(RMD)=%d, sizeof(TMD)=%d\n", 
-@@ -1775,6 +1828,11 @@
+     d->nd = nd;
  
      d->vc = qemu_new_vlan_client(nd->vlan, pcnet_receive, 
                                   pcnet_can_receive, d);
+-    
 +
-+    instance = pci_bus_num(bus) << 8 | d->dev.devfn;
-+    register_savevm("pcnet", instance, 1, pcnet_save, pcnet_load, d);
-+    register_savevm("pcnet_pci", instance, 1, generic_pci_save,
-+                    generic_pci_load, &d->dev);
-     
      snprintf(d->vc->info_str, sizeof(d->vc->info_str),
               "pcnet macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
+              d->nd->macaddr[0],
+@@ -1841,7 +1843,9 @@
+              d->nd->macaddr[5]);
+     pcnet_h_reset(d);
+-    register_savevm("pcnet", 0, 2, pcnet_save, pcnet_load, d);
++
++    instance = pci_bus_num(d->dev.bus) << 8 | d->dev.devfn;
++    register_savevm("pcnet", instance, 2, pcnet_save, pcnet_load, d);
+ }
+ /* PCI interface */
index 60127707e5f0b08f403382ece00e53ca3e5146d6..65ca34c00fd09eb3b1dd8ed39b8b9fd50aad2b88 100644 (file)
@@ -1,8 +1,8 @@
 Index: ioemu/hw/rtl8139.c
 ===================================================================
---- ioemu.orig/hw/rtl8139.c    2007-05-02 16:09:35.000000000 +0100
-+++ ioemu/hw/rtl8139.c 2007-05-02 16:10:56.000000000 +0100
-@@ -3406,6 +3406,7 @@
+--- ioemu.orig/hw/rtl8139.c    2007-05-09 14:08:41.000000000 +0100
++++ ioemu/hw/rtl8139.c 2007-05-09 14:09:34.000000000 +0100
+@@ -3414,6 +3414,7 @@
      PCIRTL8139State *d;
      RTL8139State *s;
      uint8_t *pci_conf;
@@ -10,18 +10,14 @@ Index: ioemu/hw/rtl8139.c
      
      d = (PCIRTL8139State *)pci_register_device(bus,
                                                "RTL8139", sizeof(PCIRTL8139State),
-@@ -3456,10 +3457,10 @@
+@@ -3464,8 +3465,8 @@
      s->cplus_txbuffer_len = 0;
      s->cplus_txbuffer_offset = 0;
               
 -    /* XXX: instance number ? */
--    register_savevm("rtl8139", 0, 2, rtl8139_save, rtl8139_load, s);
--    register_savevm("rtl8139_pci", 0, 1, generic_pci_save, generic_pci_load, 
--                    &d->dev);
+-    register_savevm("rtl8139", 0, 3, rtl8139_save, rtl8139_load, s);
 +    instance = pci_bus_num(bus) << 8 | s->pci_dev->devfn;
-+    register_savevm("rtl8139", instance, 2, rtl8139_save, rtl8139_load, s);
-+    register_savevm("rtl8139_pci", instance, 1, generic_pci_save, 
-+                    generic_pci_load, &d->dev);
++    register_savevm("rtl8139", instance, 3, rtl8139_save, rtl8139_load, s);
  
  #if RTL8139_ONBOARD_TIMER
      s->timer = qemu_new_timer(vm_clock, rtl8139_timer, s);
index fbb71ec67ac11b1354c3fbbfb0b7ee557395b5c2..a430f81fe301a1d20534d7f145ee3b34dba4fcdb 100644 (file)
@@ -1,8 +1,8 @@
 Index: ioemu/vl.c
 ===================================================================
---- ioemu.orig/vl.c    2007-05-03 10:07:54.000000000 +0100
-+++ ioemu/vl.c 2007-05-03 10:07:54.000000000 +0100
-@@ -828,10 +828,22 @@
+--- ioemu.orig/vl.c    2007-05-03 19:25:11.000000000 +0100
++++ ioemu/vl.c 2007-05-03 19:26:37.000000000 +0100
+@@ -915,10 +915,22 @@
  #ifdef CONFIG_DM
  static void timer_save(QEMUFile *f, void *opaque)
  {
index c6d46f8cb53ebacc1c07a8d7676ae8c350f4eaf2..7565b894478d81c0abc7f659d434b64cd200b741 100644 (file)
@@ -1,8 +1,8 @@
 Index: ioemu/hw/usb-hid.c
 ===================================================================
---- ioemu.orig/hw/usb-hid.c    2007-05-03 09:56:32.000000000 +0100
-+++ ioemu/hw/usb-hid.c 2007-05-03 10:07:54.000000000 +0100
-@@ -508,6 +508,49 @@
+--- ioemu.orig/hw/usb-hid.c    2007-05-09 14:10:50.000000000 +0100
++++ ioemu/hw/usb-hid.c 2007-05-09 14:11:27.000000000 +0100
+@@ -510,6 +510,51 @@
      qemu_free(s);
  }
  
@@ -41,18 +41,20 @@ Index: ioemu/hw/usb-hid.c
 +
 +    if ( s->kind == USB_TABLET) {
 +        fprintf(logfile, "usb_mouse_load:add usb_tablet_event.\n");
-+        qemu_add_mouse_event_handler(usb_tablet_event, s, 1);
++        qemu_add_mouse_event_handler(usb_tablet_event, s, 1, "QEMU USB Tablet");
 +    } else if ( s->kind == USB_MOUSE) {
 +        fprintf(logfile, "usb_mouse_load:add usb_mouse_event.\n");
-+        qemu_add_mouse_event_handler(usb_mouse_event, s, 0);
++        qemu_add_mouse_event_handler(usb_mouse_event, s, 0, "QEMU USB MOUSE");
 +    }
++
++    return 0;
 +}
 +
 +
  USBDevice *usb_tablet_init(void)
  {
      USBMouseState *s;
-@@ -526,6 +569,8 @@
+@@ -528,6 +573,8 @@
  
      pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Tablet");
  
@@ -61,7 +63,7 @@ Index: ioemu/hw/usb-hid.c
      return (USBDevice *)s;
  }
  
-@@ -547,5 +592,7 @@
+@@ -549,5 +596,7 @@
  
      pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Mouse");
  
@@ -71,9 +73,9 @@ Index: ioemu/hw/usb-hid.c
  }
 Index: ioemu/vl.c
 ===================================================================
---- ioemu.orig/vl.c    2007-05-03 10:07:53.000000000 +0100
-+++ ioemu/vl.c 2007-05-03 10:07:54.000000000 +0100
-@@ -3878,6 +3878,7 @@
+--- ioemu.orig/vl.c    2007-05-09 14:10:50.000000000 +0100
++++ ioemu/vl.c 2007-05-09 14:11:19.000000000 +0100
+@@ -4076,6 +4076,7 @@
      const char *p;
      USBDevice *dev;
      USBPort *port;
@@ -81,7 +83,7 @@ Index: ioemu/vl.c
  
      if (!free_usb_ports)
          return -1;
-@@ -3914,6 +3915,12 @@
+@@ -4112,6 +4113,12 @@
      free_usb_ports = port->next;
      port->next = used_usb_ports;
      used_usb_ports = port;
@@ -96,13 +98,12 @@ Index: ioemu/vl.c
  }
 Index: ioemu/hw/usb.c
 ===================================================================
---- ioemu.orig/hw/usb.c        2007-05-03 09:56:32.000000000 +0100
-+++ ioemu/hw/usb.c     2007-05-03 10:07:54.000000000 +0100
-@@ -191,3 +191,43 @@
-     }
-     return q - buf;
+--- ioemu.orig/hw/usb.c        2007-05-09 14:10:50.000000000 +0100
++++ ioemu/hw/usb.c     2007-05-09 14:11:01.000000000 +0100
+@@ -201,3 +201,42 @@
+     dev->handle_packet(dev, &p);
  }
-+
 +void generic_usb_save(QEMUFile* f, void *opaque)
 +{
 +    USBDevice *s = (USBDevice*)opaque;
@@ -144,21 +145,43 @@ Index: ioemu/hw/usb.c
 +}
 Index: ioemu/hw/usb-ohci.c
 ===================================================================
---- ioemu.orig/hw/usb-ohci.c   2007-05-03 09:56:32.000000000 +0100
-+++ ioemu/hw/usb-ohci.c        2007-05-03 10:07:54.000000000 +0100
-@@ -1186,5 +1186,7 @@
+--- ioemu.orig/hw/usb-ohci.c   2007-05-09 14:10:50.000000000 +0100
++++ ioemu/hw/usb-ohci.c        2007-05-09 14:11:01.000000000 +0100
+@@ -1215,6 +1215,20 @@
+     cpu_register_physical_memory(addr, size, ohci->mem);
+ }
++static void ohci_usb_save(QEMUFile *f, void *opaque)
++{
++    OHCIState *ohci = opaque;
++
++    pci_device_save(&ohci->pci_dev, f);
++}
++
++static int ohci_usb_load(QEMUFile *f, void *opaque, int version_id)
++{
++    OHCIState *ohci = opaque;
++
++    return pci_device_load(&ohci->pci_dev, f);
++}
++
+ void usb_ohci_init(struct PCIBus *bus, int num_ports, int devfn)
+ {
+     OHCIState *ohci;
+@@ -1265,6 +1279,8 @@
          qemu_register_usb_port(&ohci->rhport[i].port, ohci, i, ohci_attach);
      }
  
-+    register_savevm("OHCI USB", 0, 1, generic_pci_save, generic_pci_load, ohci);
++    register_savevm("OHCI USB", 0, 1, ohci_usb_save, ohci_usb_load, ohci);
 +
+     ohci->async_td = 0;
      ohci_reset(ohci);
  }
 Index: ioemu/hw/usb.h
 ===================================================================
---- ioemu.orig/hw/usb.h        2007-05-03 09:56:32.000000000 +0100
-+++ ioemu/hw/usb.h     2007-05-03 10:07:54.000000000 +0100
-@@ -176,3 +176,9 @@
+--- ioemu.orig/hw/usb.h        2007-05-09 14:10:50.000000000 +0100
++++ ioemu/hw/usb.h     2007-05-09 14:11:01.000000000 +0100
+@@ -218,3 +218,9 @@
  
  /* usb-msd.c */
  USBDevice *usb_msd_init(const char *filename);
@@ -170,9 +193,9 @@ Index: ioemu/hw/usb.h
 +
 Index: ioemu/hw/usb-uhci.c
 ===================================================================
---- ioemu.orig/hw/usb-uhci.c   2007-05-03 09:56:32.000000000 +0100
-+++ ioemu/hw/usb-uhci.c        2007-05-03 10:07:54.000000000 +0100
-@@ -638,6 +638,51 @@
+--- ioemu.orig/hw/usb-uhci.c   2007-05-09 14:10:50.000000000 +0100
++++ ioemu/hw/usb-uhci.c        2007-05-09 14:11:18.000000000 +0100
+@@ -760,6 +760,57 @@
      register_ioport_read(addr, 32, 1, uhci_ioport_readb, s);
  }
  
@@ -181,6 +204,8 @@ Index: ioemu/hw/usb-uhci.c
 +    int i;
 +    UHCIState *s = (UHCIState*)opaque;
 +
++    pci_device_save(&s->dev, f);
++
 +    qemu_put_be16s(f, &s->cmd);
 +    qemu_put_be16s(f, &s->status);
 +    qemu_put_be16s(f, &s->intr);
@@ -204,6 +229,10 @@ Index: ioemu/hw/usb-uhci.c
 +    if (version_id != 1)
 +        return -EINVAL;
 +
++    i = pci_device_load(&s->dev, f);
++    if (i < 0)
++      return i;
++
 +    qemu_get_be16s(f, &s->cmd);
 +    qemu_get_be16s(f, &s->status);
 +    qemu_get_be16s(f, &s->intr);
@@ -224,12 +253,10 @@ Index: ioemu/hw/usb-uhci.c
  void usb_uhci_init(PCIBus *bus, int devfn)
  {
      UHCIState *s;
-@@ -671,4 +716,8 @@
+@@ -793,4 +844,6 @@
         to rely on this.  */
      pci_register_io_region(&s->dev, 4, 0x20, 
                             PCI_ADDRESS_SPACE_IO, uhci_map);
 +
-+    register_savevm("UHCI_usb_pci", 0, 1, generic_pci_save, generic_pci_load, s);
-+
 +    register_savevm("UHCI usb controller", 0, 1, uhci_usb_save, uhci_usb_load, s);
  }
index 5cd37e4aa9144d9ac7e93b823833ca4936aa8d5f..6864d94b4161f495b6930f1dc909c0dfa044e461 100644 (file)
@@ -22,8 +22,8 @@ Signed-off: Herbert Xu <herbert@gondor.apana.org.au>
 
 Index: ioemu/hw/ne2000.c
 ===================================================================
---- ioemu.orig/hw/ne2000.c     2006-12-08 18:20:45.000000000 +0000
-+++ ioemu/hw/ne2000.c  2006-12-08 18:20:53.000000000 +0000
+--- ioemu.orig/hw/ne2000.c     2007-05-03 19:30:23.000000000 +0100
++++ ioemu/hw/ne2000.c  2007-05-03 20:38:52.000000000 +0100
 @@ -137,6 +137,7 @@
      uint8_t curpag;
      uint8_t mult[8]; /* multicast mask array */
index 5cb70e1ddf390a0dc7c8e7a886344503ed1167f7..93ec5abbe0382b14c3d1acee0fa9297e87409712 100644 (file)
@@ -1,8 +1,8 @@
 Index: ioemu/cpu-all.h
 ===================================================================
---- ioemu.orig/cpu-all.h       2007-05-02 16:04:46.000000000 +0100
-+++ ioemu/cpu-all.h    2007-05-02 16:05:50.000000000 +0100
-@@ -822,7 +822,7 @@
+--- ioemu.orig/cpu-all.h       2007-05-03 18:38:09.000000000 +0100
++++ ioemu/cpu-all.h    2007-05-03 19:00:05.000000000 +0100
+@@ -830,7 +830,7 @@
  
  /* memory API */
  
@@ -13,9 +13,9 @@ Index: ioemu/cpu-all.h
  extern uint8_t *phys_ram_dirty;
 Index: ioemu/hw/pc.c
 ===================================================================
---- ioemu.orig/hw/pc.c 2007-05-02 16:04:46.000000000 +0100
-+++ ioemu/hw/pc.c      2007-05-02 16:05:50.000000000 +0100
-@@ -155,7 +155,7 @@
+--- ioemu.orig/hw/pc.c 2007-05-03 18:44:07.000000000 +0100
++++ ioemu/hw/pc.c      2007-05-03 19:00:05.000000000 +0100
+@@ -156,7 +156,7 @@
  }
  
  /* hd_table must contain 4 block drivers */
@@ -24,7 +24,7 @@ Index: ioemu/hw/pc.c
  {
      RTCState *s = rtc_state;
      int val;
-@@ -610,7 +610,7 @@
+@@ -445,7 +445,7 @@
  }
  
  /* PC hardware initialisation */
@@ -33,8 +33,8 @@ Index: ioemu/hw/pc.c
                       DisplayState *ds, const char **fd_filename, int snapshot,
                       const char *kernel_filename, const char *kernel_cmdline,
                       const char *initrd_filename,
-@@ -882,7 +882,7 @@
-     }
+@@ -738,7 +738,7 @@
+ #endif
  }
  
 -static void pc_init_pci(int ram_size, int vga_ram_size, int boot_device,
@@ -42,7 +42,7 @@ Index: ioemu/hw/pc.c
                          DisplayState *ds, const char **fd_filename, 
                          int snapshot, 
                          const char *kernel_filename, 
-@@ -895,7 +895,7 @@
+@@ -751,7 +751,7 @@
               initrd_filename, 1);
  }
  
@@ -53,9 +53,9 @@ Index: ioemu/hw/pc.c
                          const char *kernel_filename, 
 Index: ioemu/vl.c
 ===================================================================
---- ioemu.orig/vl.c    2007-05-02 16:05:50.000000000 +0100
-+++ ioemu/vl.c 2007-05-02 16:05:50.000000000 +0100
-@@ -122,7 +122,7 @@
+--- ioemu.orig/vl.c    2007-05-03 18:57:23.000000000 +0100
++++ ioemu/vl.c 2007-05-03 19:00:05.000000000 +0100
+@@ -132,7 +132,7 @@
  const char* keyboard_layout = NULL;
  int64_t ticks_per_sec;
  int boot_device = 'c';
@@ -64,7 +64,7 @@ Index: ioemu/vl.c
  int pit_min_timer_count = 0;
  int nb_nics;
  NICInfo nd_table[MAX_NICS];
-@@ -5899,7 +5899,7 @@
+@@ -6818,7 +6818,7 @@
                  help();
                  break;
              case QEMU_OPTION_m:
@@ -75,9 +75,9 @@ Index: ioemu/vl.c
                  if (ram_size > PHYS_RAM_MAX_SIZE) {
 Index: ioemu/vl.h
 ===================================================================
---- ioemu.orig/vl.h    2007-05-02 16:05:50.000000000 +0100
-+++ ioemu/vl.h 2007-05-02 16:05:50.000000000 +0100
-@@ -146,7 +146,7 @@
+--- ioemu.orig/vl.h    2007-05-03 18:57:23.000000000 +0100
++++ ioemu/vl.h 2007-05-03 19:00:05.000000000 +0100
+@@ -151,7 +151,7 @@
  extern int xc_handle;
  extern int domid;
  
@@ -86,7 +86,7 @@ Index: ioemu/vl.h
  extern int bios_size;
  extern int rtc_utc;
  extern int cirrus_vga_enabled;
-@@ -561,7 +561,7 @@
+@@ -688,7 +688,7 @@
  
  #ifndef QEMU_TOOL
  
@@ -97,9 +97,9 @@ Index: ioemu/vl.h
               const char *kernel_filename, const char *kernel_cmdline,
 Index: ioemu/hw/vga.c
 ===================================================================
---- ioemu.orig/hw/vga.c        2007-05-02 16:05:50.000000000 +0100
-+++ ioemu/hw/vga.c     2007-05-02 16:05:50.000000000 +0100
-@@ -1365,7 +1365,8 @@
+--- ioemu.orig/hw/vga.c        2007-05-03 18:59:25.000000000 +0100
++++ ioemu/hw/vga.c     2007-05-03 19:00:05.000000000 +0100
+@@ -1379,7 +1379,8 @@
  static void vga_draw_graphic(VGAState *s, int full_update)
  {
      int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask;
index cb981bed87979591ab6c08e5bae30ebdfacc5724..4df57c24e2336f489c3f1d2cf97f7c85857e297d 100644 (file)
@@ -1,8 +1,8 @@
 Index: ioemu/configure
 ===================================================================
---- ioemu.orig/configure       2006-08-17 19:37:35.772589281 +0100
-+++ ioemu/configure    2006-08-17 19:50:24.735401975 +0100
-@@ -228,8 +228,6 @@
+--- ioemu.orig/configure       2007-05-03 18:49:10.000000000 +0100
++++ ioemu/configure    2007-05-03 20:29:35.000000000 +0100
+@@ -237,8 +237,6 @@
    ;;
    --enable-cocoa) cocoa="yes" ; coreaudio="yes" ; sdl="no"
    ;;
@@ -11,8 +11,8 @@ Index: ioemu/configure
    --disable-gcc-check) check_gcc="no"
    ;;
    --disable-system) softmmu="no"
-@@ -758,14 +756,6 @@
-   target_user_only="yes"
+@@ -831,14 +829,6 @@
+   target_darwin_user="yes"
  fi
  
 -if test "$target_user_only" = "no" -a "$check_gfx" = "yes" \
index b90c70c59c5242444c1aaf9a599757e00ed2ef3c..8456b6223320f27212650615416b02bb531c8f24 100644 (file)
@@ -1,22 +1,23 @@
 Index: ioemu/block.c
 ===================================================================
---- ioemu.orig/block.c 2007-05-03 14:55:04.000000000 +0100
-+++ ioemu/block.c      2007-05-03 14:59:20.000000000 +0100
-@@ -420,6 +420,8 @@
+--- ioemu.orig/block.c 2007-05-09 13:31:35.000000000 +0100
++++ ioemu/block.c      2007-05-09 13:32:33.000000000 +0100
+@@ -502,6 +502,9 @@
+     if (!drv)
+         return -ENOMEDIUM;
  
-     if (!bs->inserted)
-         return -1;
 +    if (sector_num < 0)
-+      return -1;
-     while (nb_sectors > 0) {
-         if (sector_num == 0 && bs->boot_sector_enabled) {
-@@ -458,6 +460,8 @@
-         return -1;
++      return -EINVAL;
++
+     if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
+             memcpy(buf, bs->boot_sector_data, 512);
+         sector_num++;
+@@ -539,6 +542,8 @@
+         return -ENOMEDIUM;
      if (bs->read_only)
-         return -1;
+         return -EACCES;
 +    if (sector_num < 0)
-+      return -1;
++      return -EINVAL;
      if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
          memcpy(bs->boot_sector_data, buf, 512);   
      }
index 8a22abe7a5828d445aa85af43de9dd37d53a58f6..c3c7f61a60a28a8e823b563386cc24f1f4c7523d 100644 (file)
@@ -1,8 +1,8 @@
 Index: ioemu/vl.c
 ===================================================================
---- ioemu.orig/vl.c    2007-05-03 15:20:35.000000000 +0100
-+++ ioemu/vl.c 2007-05-03 15:20:43.000000000 +0100
-@@ -126,7 +126,7 @@
+--- ioemu.orig/vl.c    2007-05-09 13:48:26.000000000 +0100
++++ ioemu/vl.c 2007-05-09 13:49:06.000000000 +0100
+@@ -136,7 +136,7 @@
  struct sockaddr_in vnclisten_addr;
  const char* keyboard_layout = NULL;
  int64_t ticks_per_sec;
@@ -11,46 +11,59 @@ Index: ioemu/vl.c
  uint64_t ram_size;
  int pit_min_timer_count = 0;
  int nb_nics;
-@@ -6150,14 +6150,14 @@
+@@ -7068,14 +7068,14 @@
                  break;
  #endif /* !CONFIG_DM */
              case QEMU_OPTION_boot:
 -                boot_device = optarg[0];
 -                if (boot_device != 'a' && 
--#ifdef TARGET_SPARC
--                  // Network boot
++                boot_device = strdup(optarg);
++                if (strspn(boot_device, "a"
+ #if defined(TARGET_SPARC) || defined(TARGET_I386)
+                   // Network boot
 -                  boot_device != 'n' &&
--#endif
++                  "n"
+ #endif
 -                    boot_device != 'c' && boot_device != 'd') {
 -                    fprintf(stderr, "qemu: invalid boot device '%c'\n", boot_device);
-+                boot_device = strdup(optarg);
-+                if (strspn(boot_device, "acd"
-+#if defined(TARGET_SPARC) || defined(TARGET_I386)
-+                           "n"
-+#endif
-+                        ) != strlen(boot_device)) {
-+                    fprintf(stderr, "qemu: invalid boot device in '%s'\n",
-+                            boot_device);
++                  "cd") != strlen(boot_device)) {
++                    fprintf(stderr, "qemu: invalid boot device in '%s'\n", boot_device);
                      exit(1);
                  }
                  break;
-@@ -6424,6 +6424,7 @@
-         fd_filename[0] == '\0')
-         help();
-     
-+#if 0
-     /* boot to cd by default if no hard disk */
-     if (hd_filename[0] == '\0' && boot_device == 'c') {
-         if (fd_filename[0] != '\0')
-@@ -6431,6 +6432,7 @@
-         else
-             boot_device = 'd';
+@@ -7442,6 +7442,7 @@
+             exit(1);
      }
-+#endif
- #endif /* !CONFIG_DM */
  
-     setvbuf(stdout, NULL, _IOLBF, 0);
-@@ -6692,6 +6694,7 @@
++#ifndef CONFIG_DM
+ #ifdef TARGET_I386
+     if (boot_device == 'n') {
+       for (i = 0; i < nb_nics; i++) {
+@@ -7463,6 +7464,7 @@
+       boot_device = 'c'; /* to prevent confusion by the BIOS */
+     }
+ #endif
++#endif /* !CONFIG_DM */
+ #if defined (__ia64__)
+     if (ram_size > MMIO_START)
+@@ -7472,6 +7474,7 @@
+     /* init the memory */
+     phys_ram_size = ram_size + vga_ram_size + bios_size;
++#ifndef CONFIG_DM
+     for (i = 0; i < nb_option_roms; i++) {
+       int ret = get_image_size(option_rom[i]);
+       if (ret == -1) {
+@@ -7480,6 +7483,7 @@
+       }
+       phys_ram_size += ret;
+     }
++#endif /* !CONFIG_DM */
+ #ifdef CONFIG_DM
+@@ -7711,6 +7715,7 @@
                    ds, fd_filename, snapshot,
                    kernel_filename, kernel_cmdline, initrd_filename,
                    timeoffset);
@@ -60,9 +73,9 @@ Index: ioemu/vl.c
      if (usb_enabled) {
 Index: ioemu/vl.h
 ===================================================================
---- ioemu.orig/vl.h    2007-05-03 15:20:39.000000000 +0100
-+++ ioemu/vl.h 2007-05-03 15:20:43.000000000 +0100
-@@ -578,7 +578,7 @@
+--- ioemu.orig/vl.h    2007-05-09 13:48:26.000000000 +0100
++++ ioemu/vl.h 2007-05-09 13:48:55.000000000 +0100
+@@ -705,7 +705,7 @@
  #ifndef QEMU_TOOL
  
  typedef void QEMUMachineInitFunc(uint64_t ram_size, int vga_ram_size, 
@@ -71,7 +84,7 @@ Index: ioemu/vl.h
               DisplayState *ds, const char **fd_filename, int snapshot,
               const char *kernel_filename, const char *kernel_cmdline,
               const char *initrd_filename, time_t timeoffset);
-@@ -1024,7 +1024,7 @@
+@@ -1219,7 +1219,7 @@
                      uint32_t start, uint32_t count);
  int PPC_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size,
                            const unsigned char *arch,
@@ -82,9 +95,9 @@ Index: ioemu/vl.h
                            uint32_t initrd_image, uint32_t initrd_size,
 Index: ioemu/hw/pc.c
 ===================================================================
---- ioemu.orig/hw/pc.c 2007-05-03 15:20:35.000000000 +0100
-+++ ioemu/hw/pc.c      2007-05-03 15:20:43.000000000 +0100
-@@ -158,8 +158,25 @@
+--- ioemu.orig/hw/pc.c 2007-05-09 13:48:26.000000000 +0100
++++ ioemu/hw/pc.c      2007-05-09 13:48:55.000000000 +0100
+@@ -159,8 +159,25 @@
      rtc_set_memory(s, info_ofs + 8, sectors);
  }
  
@@ -111,7 +124,7 @@ Index: ioemu/hw/pc.c
  {
      RTCState *s = rtc_state;
      int val;
-@@ -205,21 +222,14 @@
+@@ -191,21 +208,14 @@
      rtc_set_memory(s, 0x34, val);
      rtc_set_memory(s, 0x35, val >> 8);
      
@@ -141,7 +154,7 @@ Index: ioemu/hw/pc.c
  
      /* floppy type */
  
-@@ -617,7 +627,7 @@
+@@ -451,7 +461,7 @@
  #define NOBIOS 1
  
  /* PC hardware initialisation */
@@ -150,8 +163,8 @@ Index: ioemu/hw/pc.c
                       DisplayState *ds, const char **fd_filename, int snapshot,
                       const char *kernel_filename, const char *kernel_cmdline,
                       const char *initrd_filename, time_t timeoffset,
-@@ -919,7 +929,7 @@
-     }
+@@ -772,7 +782,7 @@
+ #endif
  }
  
 -static void pc_init_pci(uint64_t ram_size, int vga_ram_size, int boot_device,
@@ -159,7 +172,7 @@ Index: ioemu/hw/pc.c
                          DisplayState *ds, const char **fd_filename, 
                          int snapshot, 
                          const char *kernel_filename, 
-@@ -933,7 +943,7 @@
+@@ -786,7 +796,7 @@
               initrd_filename, timeoffset, 1);
  }
  
index 19f64c8925754700e826a0b8c3112cdc00a3eda6..8a3851e35b67c5f53eaf1886fb5fae25eae0ce86 100644 (file)
@@ -1,8 +1,8 @@
 Index: ioemu/console.c
 ===================================================================
---- ioemu.orig/console.c       2006-08-06 02:03:45.803444993 +0100
-+++ ioemu/console.c    2006-08-06 02:15:48.546894051 +0100
-@@ -505,7 +505,7 @@
+--- ioemu.orig/console.c       2007-05-03 18:17:55.000000000 +0100
++++ ioemu/console.c    2007-05-03 19:00:14.000000000 +0100
+@@ -503,7 +503,7 @@
              c++;
          }
      }
@@ -11,7 +11,7 @@ Index: ioemu/console.c
      s->cells = cells;
  }
  
-@@ -1032,11 +1032,21 @@
+@@ -1156,11 +1156,21 @@
      return !active_console->text_console;
  }
  
@@ -34,7 +34,7 @@ Index: ioemu/console.c
      static int color_inited;
  
      chr = qemu_mallocz(sizeof(CharDriverState));
-@@ -1058,12 +1068,7 @@
+@@ -1182,12 +1192,7 @@
      
      if (!color_inited) {
          color_inited = 1;
@@ -48,15 +48,3 @@ Index: ioemu/console.c
      }
      s->y_displayed = 0;
      s->y_base = 0;
-Index: ioemu/vl.c
-===================================================================
---- ioemu.orig/vl.c    2006-08-06 02:15:39.711878977 +0100
-+++ ioemu/vl.c 2006-08-06 02:15:48.550893605 +0100
-@@ -3671,6 +3671,7 @@
-             if (net_tap_fd_init(vlan, fd))
-                 ret = 0;
-         } else {
-+            ifname[0] = '\0';
-             get_param_value(ifname, sizeof(ifname), "ifname", p);
-             if (get_param_value(setup_script, sizeof(setup_script), "script", p) == 0) {
-                 pstrcpy(setup_script, sizeof(setup_script), DEFAULT_NETWORK_SCRIPT);
index 8fe20925bba9daa86cf831837d60c2b55b571fd4..171503efcbc2d8652789f96f26f7917b70404230 100644 (file)
@@ -1,7 +1,7 @@
 Index: ioemu/hw/cirrus_vga.c
 ===================================================================
---- ioemu.orig/hw/cirrus_vga.c 2007-05-03 14:55:45.000000000 +0100
-+++ ioemu/hw/cirrus_vga.c      2007-05-03 14:58:05.000000000 +0100
+--- ioemu.orig/hw/cirrus_vga.c 2007-05-03 20:36:50.000000000 +0100
++++ ioemu/hw/cirrus_vga.c      2007-05-03 20:57:47.000000000 +0100
 @@ -601,7 +601,8 @@
        off_cur_end = off_cur + bytesperline;
        off_cur &= TARGET_PAGE_MASK;
@@ -14,8 +14,8 @@ Index: ioemu/hw/cirrus_vga.c
        off_begin += off_pitch;
 Index: ioemu/hw/cirrus_vga_rop.h
 ===================================================================
---- ioemu.orig/hw/cirrus_vga_rop.h     2007-05-02 10:30:05.000000000 +0100
-+++ ioemu/hw/cirrus_vga_rop.h  2007-05-03 14:58:22.000000000 +0100
+--- ioemu.orig/hw/cirrus_vga_rop.h     2007-05-03 18:17:34.000000000 +0100
++++ ioemu/hw/cirrus_vga_rop.h  2007-05-03 20:57:47.000000000 +0100
 @@ -22,18 +22,36 @@
   * THE SOFTWARE.
   */
@@ -89,8 +89,8 @@ Index: ioemu/hw/cirrus_vga_rop.h
 +#undef m
 Index: ioemu/hw/cirrus_vga_rop2.h
 ===================================================================
---- ioemu.orig/hw/cirrus_vga_rop2.h    2007-05-02 10:30:05.000000000 +0100
-+++ ioemu/hw/cirrus_vga_rop2.h 2007-05-03 14:58:42.000000000 +0100
+--- ioemu.orig/hw/cirrus_vga_rop2.h    2007-05-03 18:17:34.000000000 +0100
++++ ioemu/hw/cirrus_vga_rop2.h 2007-05-03 20:57:47.000000000 +0100
 @@ -23,36 +23,42 @@
   */
  
index b768d288911976872bbb1ea605d43c9d8bcd62c9..6e27055df666dc4a74983af9a93482e3afb4ef7b 100644 (file)
@@ -1,8 +1,8 @@
 Index: ioemu/hw/vga.c
 ===================================================================
---- ioemu.orig/hw/vga.c        2007-05-02 16:04:46.000000000 +0100
-+++ ioemu/hw/vga.c     2007-05-02 16:05:50.000000000 +0100
-@@ -1622,7 +1622,9 @@
+--- ioemu.orig/hw/vga.c        2007-05-03 18:18:01.000000000 +0100
++++ ioemu/hw/vga.c     2007-05-03 18:59:25.000000000 +0100
+@@ -1636,7 +1636,9 @@
  static void vga_save(QEMUFile *f, void *opaque)
  {
      VGAState *s = opaque;
@@ -10,25 +10,25 @@ Index: ioemu/hw/vga.c
      int i;
 +#endif
  
-     qemu_put_be32s(f, &s->latch);
-     qemu_put_8s(f, &s->sr_index);
-@@ -1663,7 +1665,10 @@
+     if (s->pci_dev)
+         pci_device_save(s->pci_dev, f);
+@@ -1680,7 +1682,10 @@
  static int vga_load(QEMUFile *f, void *opaque, int version_id)
  {
      VGAState *s = opaque;
--    int is_vbe, i;
-+    int is_vbe;
+-    int is_vbe, i, ret;
++    int is_vbe, ret;
 +#ifdef CONFIG_BOCHS_VBE
 +    int i;
 +#endif
  
-     if (version_id != 1)
+     if (version_id > 2)
          return -EINVAL;
 Index: ioemu/vl.c
 ===================================================================
---- ioemu.orig/vl.c    2007-05-02 16:05:50.000000000 +0100
-+++ ioemu/vl.c 2007-05-02 16:05:50.000000000 +0100
-@@ -39,6 +39,7 @@
+--- ioemu.orig/vl.c    2007-05-03 18:57:13.000000000 +0100
++++ ioemu/vl.c 2007-05-03 18:57:23.000000000 +0100
+@@ -40,6 +40,7 @@
  #include <sys/ioctl.h>
  #include <sys/socket.h>
  #include <netinet/in.h>
@@ -36,7 +36,7 @@ Index: ioemu/vl.c
  #include <dirent.h>
  #include <netdb.h>
  #ifdef _BSD
-@@ -2932,7 +2933,7 @@
+@@ -3129,7 +3130,7 @@
      }
  
      /* XXX: better tmp dir construction */
@@ -45,7 +45,7 @@ Index: ioemu/vl.c
      if (mkdir(smb_dir, 0700) < 0) {
          fprintf(stderr, "qemu: could not create samba server dir '%s'\n", smb_dir);
          exit(1);
-@@ -3893,7 +3894,7 @@
+@@ -4092,7 +4093,7 @@
                  perror("Opening pidfile");
                  exit(1);
              }
@@ -54,7 +54,7 @@ Index: ioemu/vl.c
              fclose(f);
              pid_filename = qemu_strdup(filename);
              if (!pid_filename) {
-@@ -5308,7 +5309,9 @@
+@@ -6207,7 +6208,9 @@
      QEMU_OPTION_d,
      QEMU_OPTION_hdachs,
      QEMU_OPTION_L,
@@ -64,7 +64,7 @@ Index: ioemu/vl.c
      QEMU_OPTION_k,
      QEMU_OPTION_localtime,
      QEMU_OPTION_cirrusvga,
-@@ -5379,7 +5382,9 @@
+@@ -6284,7 +6287,9 @@
      { "d", HAS_ARG, QEMU_OPTION_d },
      { "hdachs", HAS_ARG, QEMU_OPTION_hdachs },
      { "L", HAS_ARG, QEMU_OPTION_L },
@@ -74,7 +74,7 @@ Index: ioemu/vl.c
  #ifdef USE_KQEMU
      { "no-kqemu", 0, QEMU_OPTION_no_kqemu },
      { "kernel-kqemu", 0, QEMU_OPTION_kernel_kqemu },
-@@ -5853,9 +5858,11 @@
+@@ -6772,9 +6777,11 @@
                  fd_bootchk = 0;
                  break;
  #endif
@@ -88,9 +88,9 @@ Index: ioemu/vl.c
                      fprintf(stderr, "qemu: too many network clients\n");
 Index: ioemu/vl.h
 ===================================================================
---- ioemu.orig/vl.h    2007-05-02 16:05:50.000000000 +0100
-+++ ioemu/vl.h 2007-05-02 16:05:50.000000000 +0100
-@@ -957,7 +957,7 @@
+--- ioemu.orig/vl.h    2007-05-03 18:49:10.000000000 +0100
++++ ioemu/vl.h 2007-05-03 18:57:23.000000000 +0100
+@@ -1133,7 +1133,7 @@
               unsigned long vram_offset, int vram_size, int width, int height);
  
  /* slavio_intctl.c */
@@ -101,13 +101,12 @@ Index: ioemu/vl.h
  void slavio_irq_info(void *opaque);
 Index: ioemu/usb-linux.c
 ===================================================================
---- ioemu.orig/usb-linux.c     2007-05-02 16:04:46.000000000 +0100
-+++ ioemu/usb-linux.c  2007-05-02 16:05:50.000000000 +0100
-@@ -26,7 +26,9 @@
+--- ioemu.orig/usb-linux.c     2007-05-03 18:17:59.000000000 +0100
++++ ioemu/usb-linux.c  2007-05-03 18:59:55.000000000 +0100
+@@ -26,6 +26,9 @@
  #if defined(__linux__)
  #include <dirent.h>
  #include <sys/ioctl.h>
--#include <linux/compiler.h>
 +/* Some versions of usbdevice_fs.h need __user to be defined for them.   */
 +/* This may (harmlessly) conflict with a definition in linux/compiler.h. */
 +#define __user
index ca44e865db0d7aae0246bf377ad5159b79ef61cd..aae37c45d393ca7cca5c82c174f3927d80a98908 100644 (file)
@@ -2,9 +2,9 @@ Changes required because qemu-dm runs daemonized.
 
 Index: ioemu/vl.c
 ===================================================================
---- ioemu.orig/vl.c    2007-05-03 10:11:05.000000000 +0100
-+++ ioemu/vl.c 2007-05-03 10:11:05.000000000 +0100
-@@ -6129,10 +6129,11 @@
+--- ioemu.orig/vl.c    2007-05-03 20:30:30.000000000 +0100
++++ ioemu/vl.c 2007-05-03 20:32:07.000000000 +0100
+@@ -7047,10 +7047,11 @@
                  }
                  break;
              case QEMU_OPTION_nographic:
index 5e7b8c0f14246948ea7ceb9b682887fba17bd6c7..fb88aff8a1031fe22a2546dd2395c86653a3a798 100644 (file)
@@ -1,21 +1,21 @@
 Index: ioemu/Makefile.target
 ===================================================================
---- ioemu.orig/Makefile.target 2007-05-02 15:48:40.000000000 +0100
-+++ ioemu/Makefile.target      2007-05-02 16:04:46.000000000 +0100
-@@ -303,7 +303,7 @@
+--- ioemu.orig/Makefile.target 2007-05-09 13:47:24.000000000 +0100
++++ ioemu/Makefile.target      2007-05-09 14:08:42.000000000 +0100
+@@ -332,7 +332,7 @@
  endif
  
  # must use static linking to avoid leaving stuff in virtual address space
--VL_OBJS=vl.o osdep.o block.o readline.o monitor.o pci.o console.o loader.o
-+VL_OBJS=vl.o osdep.o block.o readline.o monitor.o pci.o console.o
- VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o block-dmg.o block-bochs.o block-vpc.o block-vvfat.o
- ifdef CONFIG_WIN32
- VL_OBJS+=tap-win32.o
+-VL_OBJS=vl.o osdep.o readline.o monitor.o pci.o console.o loader.o isa_mmio.o
++VL_OBJS=vl.o osdep.o readline.o monitor.o pci.o console.o isa_mmio.o
+ VL_OBJS+=cutils.o
+ VL_OBJS+=block.o block-raw.o
+ VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o block-dmg.o block-bochs.o block-vpc.o block-vvfat.o block-qcow2.o
 Index: ioemu/configure
 ===================================================================
---- ioemu.orig/configure       2007-05-02 15:48:40.000000000 +0100
-+++ ioemu/configure    2007-05-02 16:04:46.000000000 +0100
-@@ -75,8 +75,8 @@
+--- ioemu.orig/configure       2007-05-09 13:47:24.000000000 +0100
++++ ioemu/configure    2007-05-09 14:08:42.000000000 +0100
+@@ -77,8 +77,8 @@
  bigendian="no"
  mingw32="no"
  EXESUF=""
@@ -26,7 +26,7 @@ Index: ioemu/configure
  adlib="no"
  oss="no"
  dsound="no"
-@@ -749,6 +749,8 @@
+@@ -812,6 +812,8 @@
  if expr $target : '.*-softmmu' > /dev/null ; then
    target_softmmu="yes"
  fi
@@ -37,8 +37,8 @@ Index: ioemu/configure
    target_user_only="yes"
 Index: ioemu/cpu-all.h
 ===================================================================
---- ioemu.orig/cpu-all.h       2007-05-02 15:48:36.000000000 +0100
-+++ ioemu/cpu-all.h    2007-05-02 16:04:46.000000000 +0100
+--- ioemu.orig/cpu-all.h       2007-05-09 13:47:22.000000000 +0100
++++ ioemu/cpu-all.h    2007-05-09 14:08:42.000000000 +0100
 @@ -690,7 +690,9 @@
  void page_set_flags(target_ulong start, target_ulong end, int flags);
  void page_unprotect_range(target_ulong data, target_ulong data_size);
@@ -49,7 +49,7 @@ Index: ioemu/cpu-all.h
  #ifdef SINGLE_CPU_DEFINES
  
  #if defined(TARGET_I386)
-@@ -745,6 +747,12 @@
+@@ -752,6 +754,12 @@
  
  #endif
  
@@ -64,8 +64,8 @@ Index: ioemu/cpu-all.h
  void cpu_dump_state(CPUState *env, FILE *f, 
 Index: ioemu/disas.h
 ===================================================================
---- ioemu.orig/disas.h 2007-05-02 15:48:36.000000000 +0100
-+++ ioemu/disas.h      2007-05-02 15:48:40.000000000 +0100
+--- ioemu.orig/disas.h 2007-05-09 13:47:22.000000000 +0100
++++ ioemu/disas.h      2007-05-09 13:47:24.000000000 +0100
 @@ -1,6 +1,7 @@
  #ifndef _QEMU_DISAS_H
  #define _QEMU_DISAS_H
@@ -83,9 +83,9 @@ Index: ioemu/disas.h
  #endif /* _QEMU_DISAS_H */
 Index: ioemu/exec-all.h
 ===================================================================
---- ioemu.orig/exec-all.h      2007-05-02 15:48:36.000000000 +0100
-+++ ioemu/exec-all.h   2007-05-02 16:04:45.000000000 +0100
-@@ -509,7 +509,7 @@
+--- ioemu.orig/exec-all.h      2007-05-09 13:47:22.000000000 +0100
++++ ioemu/exec-all.h   2007-05-09 14:08:42.000000000 +0100
+@@ -519,7 +519,7 @@
  
  extern int tb_invalidated_flag;
  
@@ -94,7 +94,7 @@ Index: ioemu/exec-all.h
  
  void tlb_fill(target_ulong addr, int is_write, int is_user, 
                void *retaddr);
-@@ -536,7 +536,7 @@
+@@ -546,7 +546,7 @@
  
  #endif
  
@@ -105,17 +105,17 @@ Index: ioemu/exec-all.h
      return addr;
 Index: ioemu/hw/pc.c
 ===================================================================
---- ioemu.orig/hw/pc.c 2007-05-02 15:48:36.000000000 +0100
-+++ ioemu/hw/pc.c      2007-05-02 16:04:46.000000000 +0100
-@@ -73,6 +73,7 @@
+--- ioemu.orig/hw/pc.c 2007-05-09 13:47:22.000000000 +0100
++++ ioemu/hw/pc.c      2007-05-09 14:08:42.000000000 +0100
+@@ -74,6 +74,7 @@
      }
  }
  
 +#ifndef CONFIG_DM
- /* IRQ handling */
int cpu_get_pic_interrupt(CPUState *env)
+ /* SMM support */
void cpu_smm_update(CPUState *env)
  {
-@@ -89,6 +90,7 @@
+@@ -98,6 +99,7 @@
      intno = pic_read_irq(isa_pic);
      return intno;
  }
@@ -123,23 +123,7 @@ Index: ioemu/hw/pc.c
  
  static void pic_irq_request(void *opaque, int level)
  {
-@@ -400,6 +402,7 @@
- /*************************************************/
-+#ifndef CONFIG_DM
- static void putb(uint8_t **pp, int val)
- {
-     uint8_t *q;
-@@ -546,6 +549,7 @@
-     float_pointer_struct[10] = 
-         -mpf_checksum(float_pointer_struct, q - float_pointer_struct);
- }
-+#endif /* !CONFIG_DM */
- static const int ide_iobase[2] = { 0x1f0, 0x170 };
-@@ -626,12 +630,14 @@
+@@ -463,12 +465,14 @@
      /* init CPUs */
      for(i = 0; i < smp_cpus; i++) {
          env = cpu_init();
@@ -151,10 +135,10 @@ Index: ioemu/hw/pc.c
              env->cpuid_features |= CPUID_APIC;
          }
 +#endif /* !CONFIG_DM */
-         register_savevm("cpu", i, 3, cpu_save, cpu_load, env);
+         register_savevm("cpu", i, 4, cpu_save, cpu_load, env);
          qemu_register_reset(main_cpu_reset, env);
          if (pci_enabled) {
-@@ -690,6 +696,7 @@
+@@ -541,6 +545,7 @@
      
      bochs_bios_init();
  
@@ -162,15 +146,15 @@ Index: ioemu/hw/pc.c
      if (linux_boot) {
          uint8_t bootsect[512];
          uint8_t old_bootsect[512];
-@@ -745,6 +752,7 @@
+@@ -596,6 +601,7 @@
          /* loader type */
          stw_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x210, 0x01);
      }
 +#endif /* !CONFIG_DM */
  
      if (pci_enabled) {
-         pci_bus = i440fx_init();
-@@ -783,9 +791,11 @@
+         pci_bus = i440fx_init(&i440fx_state);
+@@ -639,9 +645,11 @@
      isa_pic = pic_init(pic_irq_request, first_cpu);
      pit = pit_init(0x40, 0);
      pcspk_init(pit);
@@ -184,8 +168,8 @@ Index: ioemu/hw/pc.c
          if (serial_hds[i]) {
 Index: ioemu/hw/vga_int.h
 ===================================================================
---- ioemu.orig/hw/vga_int.h    2007-05-02 15:48:36.000000000 +0100
-+++ ioemu/hw/vga_int.h 2007-05-02 16:04:45.000000000 +0100
+--- ioemu.orig/hw/vga_int.h    2007-05-09 13:47:22.000000000 +0100
++++ ioemu/hw/vga_int.h 2007-05-09 14:08:41.000000000 +0100
 @@ -28,7 +28,7 @@
  #define ST01_DISP_ENABLE    0x01
  
@@ -197,9 +181,9 @@ Index: ioemu/hw/vga_int.h
  #define VBE_DISPI_MAX_YRES              1200
 Index: ioemu/monitor.c
 ===================================================================
---- ioemu.orig/monitor.c       2007-05-02 15:48:36.000000000 +0100
-+++ ioemu/monitor.c    2007-05-02 16:04:46.000000000 +0100
-@@ -68,6 +68,12 @@
+--- ioemu.orig/monitor.c       2007-05-09 13:47:22.000000000 +0100
++++ ioemu/monitor.c    2007-05-09 14:08:59.000000000 +0100
+@@ -69,6 +69,12 @@
  
  void term_flush(void)
  {
@@ -212,15 +196,15 @@ Index: ioemu/monitor.c
      if (term_outbuf_index > 0) {
          qemu_chr_write(monitor_hd, term_outbuf, term_outbuf_index);
          term_outbuf_index = 0;
-@@ -106,6 +112,7 @@
-     va_end(ap);
+@@ -134,6 +140,7 @@
+     }
  }
  
 +#ifndef CONFIG_DM
  static int monitor_fprintf(FILE *stream, const char *fmt, ...)
  {
      va_list ap;
-@@ -114,6 +121,7 @@
+@@ -142,6 +149,7 @@
      va_end(ap);
      return 0;
  }
@@ -228,7 +212,7 @@ Index: ioemu/monitor.c
  
  static int compare_cmd(const char *name, const char *list)
  {
-@@ -227,6 +235,7 @@
+@@ -258,6 +266,7 @@
      return mon_cpu;
  }
  
@@ -236,7 +220,7 @@ Index: ioemu/monitor.c
  static void do_info_registers(void)
  {
      CPUState *env;
-@@ -280,6 +289,7 @@
+@@ -311,6 +320,7 @@
  {
      dump_exec_info(NULL, monitor_fprintf);
  }
@@ -244,23 +228,23 @@ Index: ioemu/monitor.c
  
  static void do_info_history (void)
  {
-@@ -377,6 +387,7 @@
+@@ -408,6 +418,7 @@
      cpu_set_log(mask);
  }
  
 +#ifndef CONFIG_DM
- static void do_savevm(const char *filename)
+ static void do_stop(void)
  {
-     if (qemu_savevm(filename) < 0)
-@@ -623,6 +634,7 @@
- #endif
-     term_printf("\n");
+     vm_stop(EXCP_INTERRUPT);
+@@ -672,6 +683,7 @@
+     }
+     fclose(f);
  }
 +#endif /* !CONFIG_DM */
  
  static void do_sum(uint32_t start, uint32_t size)
  {
-@@ -841,6 +853,7 @@
+@@ -890,6 +902,7 @@
      kbd_mouse_event(0, 0, 0, mouse_button_state);
  }
  
@@ -268,7 +252,7 @@ Index: ioemu/monitor.c
  static void do_ioport_read(int count, int format, int size, int addr, int has_index, int index)
  {
      uint32_t val;
-@@ -1031,6 +1044,7 @@
+@@ -1080,6 +1093,7 @@
      term_printf("kqemu support: not compiled\n");
  #endif
  } 
@@ -276,15 +260,15 @@ Index: ioemu/monitor.c
  
  #ifdef CONFIG_PROFILER
  
-@@ -1152,6 +1166,7 @@
+@@ -1201,6 +1215,7 @@
        "filename", "save screen into PPM image 'filename'" },
      { "log", "s", do_log,
        "item1[,...]", "activate logging of the specified items to '/tmp/qemu.log'" }, 
 +#ifndef CONFIG_DM
-     { "savevm", "F", do_savevm,
-       "filename", "save the whole virtual machine state to 'filename'" }, 
-     { "loadvm", "F", do_loadvm,
-@@ -1172,21 +1187,26 @@
+     { "savevm", "s?", do_savevm,
+       "tag|id", "save a VM snapshot. If no tag or id are provided, a new snapshot is created" }, 
+     { "loadvm", "s", do_loadvm,
+@@ -1223,21 +1238,26 @@
        "/fmt expr", "print expression value (use $reg for CPU register access)", },
      { "i", "/ii.", do_ioport_read, 
        "/fmt addr", "I/O port read" },
@@ -311,7 +295,18 @@ Index: ioemu/monitor.c
      { "mouse_move", "sss?", do_mouse_move, 
        "dx dy [dz]", "send mouse move events" },
      { "mouse_button", "i", do_mouse_button, 
-@@ -1208,10 +1228,12 @@
+@@ -1251,8 +1271,10 @@
+ #endif
+      { "stopcapture", "i", do_stop_capture,
+        "capture index", "stop capture" },
++#ifndef CONFIG_DM
+     { "memsave", "lis", do_memory_save, 
+       "addr size file", "save to disk virtual memory dump starting at 'addr' of size 'size'", },
++#endif /* !CONFIG_DM */
+     { NULL, NULL, }, 
+ };
+@@ -1263,10 +1285,12 @@
        "", "show the network state" },
      { "block", "", do_info_block,
        "", "show the block devices" },
@@ -324,7 +319,7 @@ Index: ioemu/monitor.c
      { "history", "", do_info_history,
        "", "show the command line history", },
      { "irq", "", irq_info,
-@@ -1220,6 +1242,7 @@
+@@ -1275,6 +1299,7 @@
        "", "show i8259 (PIC) state", },
      { "pci", "", pci_info,
        "", "show PCI info", },
@@ -332,7 +327,7 @@ Index: ioemu/monitor.c
  #if defined(TARGET_I386)
      { "tlb", "", tlb_info,
        "", "show virtual to physical memory mappings", },
-@@ -1230,6 +1253,7 @@
+@@ -1285,6 +1310,7 @@
        "", "show dynamic compiler info", },
      { "kqemu", "", do_info_kqemu,
        "", "show kqemu information", },
@@ -340,7 +335,7 @@ Index: ioemu/monitor.c
      { "usb", "", usb_info,
        "", "show guest USB devices", },
      { "usbhost", "", usb_host_info,
-@@ -1243,6 +1267,7 @@
+@@ -1304,6 +1330,7 @@
  
  /*******************************************************************/
  
@@ -348,7 +343,7 @@ Index: ioemu/monitor.c
  static const char *pch;
  static jmp_buf expr_env;
  
-@@ -1786,6 +1811,7 @@
+@@ -1847,6 +1874,7 @@
      *pp = pch;
      return 0;
  }
@@ -356,7 +351,7 @@ Index: ioemu/monitor.c
  
  static int get_str(char *buf, int buf_size, const char **pp)
  {
-@@ -1852,8 +1878,10 @@
+@@ -1913,8 +1941,10 @@
      return 0;
  }
  
@@ -367,7 +362,7 @@ Index: ioemu/monitor.c
  
  #define MAX_ARGS 16
  
-@@ -1861,7 +1889,10 @@
+@@ -1922,7 +1952,10 @@
  {
      const char *p, *pstart, *typestr;
      char *q;
@@ -379,7 +374,7 @@ Index: ioemu/monitor.c
      term_cmd_t *cmd;
      char cmdname[256];
      char buf[1024];
-@@ -1953,6 +1984,7 @@
+@@ -2014,6 +2047,7 @@
                  args[nb_args++] = str;
              }
              break;
@@ -387,7 +382,7 @@ Index: ioemu/monitor.c
          case '/':
              {
                  int count, format, size;
-@@ -2085,6 +2117,7 @@
+@@ -2146,6 +2180,7 @@
                  }
              }
              break;
@@ -395,7 +390,7 @@ Index: ioemu/monitor.c
          case '-':
              {
                  int has_option;
-@@ -2111,6 +2144,11 @@
+@@ -2172,6 +2207,11 @@
                  args[nb_args++] = (void *)has_option;
              }
              break;
@@ -407,7 +402,7 @@ Index: ioemu/monitor.c
          default:
          bad_type:
              term_printf("%s: unknown type '%c'\n", cmdname, c);
-@@ -2161,6 +2199,7 @@
+@@ -2222,6 +2262,7 @@
      return;
  }
  
@@ -415,7 +410,7 @@ Index: ioemu/monitor.c
  static void cmd_completion(const char *name, const char *list)
  {
      const char *p, *pstart;
-@@ -2354,6 +2393,11 @@
+@@ -2415,6 +2456,11 @@
      for(i = 0; i < nb_args; i++)
          qemu_free(args[i]);
  }
@@ -429,9 +424,9 @@ Index: ioemu/monitor.c
  {
 Index: ioemu/vl.c
 ===================================================================
---- ioemu.orig/vl.c    2007-05-02 15:48:36.000000000 +0100
-+++ ioemu/vl.c 2007-05-02 16:05:40.000000000 +0100
-@@ -422,12 +422,15 @@
+--- ioemu.orig/vl.c    2007-05-09 13:47:22.000000000 +0100
++++ ioemu/vl.c 2007-05-09 14:08:42.000000000 +0100
+@@ -396,12 +396,15 @@
  void hw_error(const char *fmt, ...)
  {
      va_list ap;
@@ -447,7 +442,7 @@ Index: ioemu/vl.c
      for(env = first_cpu; env != NULL; env = env->next_cpu) {
          fprintf(stderr, "CPU #%d:\n", env->cpu_index);
  #ifdef TARGET_I386
-@@ -436,6 +439,7 @@
+@@ -410,6 +413,7 @@
          cpu_dump_state(env, stderr, fprintf, 0);
  #endif
      }
@@ -455,16 +450,16 @@ Index: ioemu/vl.c
      va_end(ap);
      abort();
  }
-@@ -4336,6 +4340,7 @@
-     return ret;
+@@ -4953,6 +4957,7 @@
+     qemu_free(sn_tab);
  }
  
 +#ifndef CONFIG_DM
  /***********************************************************/
  /* cpu save/restore */
  
-@@ -4770,6 +4775,25 @@
-     }
+@@ -5582,6 +5587,25 @@
+     ram_decompress_close(s);
      return 0;
  }
 +#else  /* CONFIG_DM */
@@ -488,8 +483,8 @@ Index: ioemu/vl.c
 +#endif /* CONFIG_DM */
  
  /***********************************************************/
- /* machine registration */
-@@ -5664,15 +5688,19 @@
+ /* bottom halves (can be seen as timers which expire ASAP) */
+@@ -6580,15 +6604,19 @@
  #endif
      cyls = heads = secs = 0;
      translation = BIOS_ATA_TRANSLATION_AUTO;
@@ -513,7 +508,7 @@ Index: ioemu/vl.c
          parallel_devices[i][0] = '\0';
      parallel_device_index = 0;
      
-@@ -6054,6 +6082,7 @@
+@@ -7040,6 +7068,7 @@
      socket_init();
  #endif
  
@@ -521,7 +516,7 @@ Index: ioemu/vl.c
      /* init network clients */
      if (nb_net_clients == 0) {
          /* if no clients, we use a default config */
-@@ -6063,6 +6092,7 @@
+@@ -7049,6 +7078,7 @@
                  "user");
          nb_net_clients = 2;
      }
index 2087fc056f8750e22e565bd4f2d70add6b100cb9..9cdf9d64c51e7ae59193c76e12f2a7de143f4271 100644 (file)
@@ -1,7 +1,7 @@
 Index: ioemu/hw/dma.c
 ===================================================================
---- ioemu.orig/hw/dma.c        2007-05-02 10:30:05.000000000 +0100
-+++ ioemu/hw/dma.c     2007-05-03 14:59:53.000000000 +0100
+--- ioemu.orig/hw/dma.c        2007-05-03 18:17:33.000000000 +0100
++++ ioemu/hw/dma.c     2007-05-03 20:59:42.000000000 +0100
 @@ -340,6 +340,8 @@
  #endif
  
index 697422a19a5dd2df8e02f0045001f519d02aba76..63adac9ab1e2a34b178b71c7cbb4dcdec3dd9c21 100644 (file)
@@ -1,8 +1,8 @@
 Index: ioemu/monitor.c
 ===================================================================
---- ioemu.orig/monitor.c       2006-08-06 02:15:01.772108510 +0100
-+++ ioemu/monitor.c    2006-08-06 02:17:10.847719223 +0100
-@@ -2425,15 +2425,14 @@
+--- ioemu.orig/monitor.c       2007-05-09 14:09:10.000000000 +0100
++++ ioemu/monitor.c    2007-05-09 14:09:10.000000000 +0100
+@@ -2488,7 +2488,7 @@
  
  static void monitor_start_input(void)
  {
@@ -10,13 +10,14 @@ Index: ioemu/monitor.c
 +    readline_start("(HVMXen) ", 0, monitor_handle_command1, NULL);
  }
  
- void monitor_init(CharDriverState *hd, int show_banner)
- {
-     monitor_hd = hd;
-     if (show_banner) {
--        term_printf("QEMU %s monitor - type 'help' for more information\n",
--                    QEMU_VERSION);
-+        term_printf("HVM device model. type 'q' to exit\n");
-     }
-     qemu_chr_add_read_handler(hd, term_can_read, term_read, NULL);
+ static void term_event(void *opaque, int event)
+@@ -2497,8 +2497,7 @@
+       return;
+     if (!hide_banner)
+-          term_printf("QEMU %s monitor - type 'help' for more information\n",
+-                      QEMU_VERSION);
++      term_printf("HVM device model. type 'q' to exit\n");
      monitor_start_input();
+ }
index 1bd4d7e60eb2a3c4d610889215f1f857ed66e31b..0fbc88f84c6ae87aeef692265b465cd2cc91645c 100644 (file)
@@ -1,7 +1,8 @@
-diff -r ead4d7bbf711 cpu-all.h
---- a/cpu-all.h        Tue May 30 13:32:07 2006 +0100
-+++ b/cpu-all.h        Tue May 30 13:32:25 2006 +0100
-@@ -820,6 +820,23 @@ int cpu_inl(CPUState *env, int addr);
+Index: ioemu/cpu-all.h
+===================================================================
+--- ioemu.orig/cpu-all.h       2007-05-03 19:00:05.000000000 +0100
++++ ioemu/cpu-all.h    2007-05-03 19:00:55.000000000 +0100
+@@ -828,6 +828,23 @@
  int cpu_inl(CPUState *env, int addr);
  #endif
  
index 15c5969b2ceb53c31e4915e039df684a4810228c..4cba5b7ac9baf5ad7dec4e9266fb334cf6f4a530 100644 (file)
@@ -1,8 +1,8 @@
 Index: ioemu/hw/vga.c
 ===================================================================
---- ioemu.orig/hw/vga.c        2006-08-06 02:22:01.441324863 +0100
-+++ ioemu/hw/vga.c     2006-08-06 02:22:46.606290142 +0100
-@@ -1728,6 +1728,136 @@
+--- ioemu.orig/hw/vga.c        2007-05-03 19:00:05.000000000 +0100
++++ ioemu/hw/vga.c     2007-05-03 19:11:39.000000000 +0100
+@@ -1757,6 +1757,136 @@
      }
  }
  
@@ -139,12 +139,12 @@ Index: ioemu/hw/vga.c
  void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base, 
                       unsigned long vga_ram_offset, int vga_ram_size)
  {
-@@ -1769,6 +1899,8 @@
+@@ -1796,6 +1926,8 @@
+     s->get_resolution = vga_get_resolution;
+     graphic_console_init(s->ds, vga_update_display, vga_invalidate_display,
                           vga_screen_dump, s);
-     /* XXX: currently needed for display */
-     vga_state = s;
 +
 +    vga_bios_init(s);
  }
  
+ /* used by both ISA and PCI */
index 77674e9480a55dd6bf7dab72c8a33a6a9437c6a0..61ae332428b76dc0345ddecf8de25c90fdb961cf 100644 (file)
@@ -1,8 +1,8 @@
 Index: ioemu/vl.c
 ===================================================================
---- ioemu.orig/vl.c    2007-05-02 16:05:51.000000000 +0100
-+++ ioemu/vl.c 2007-05-02 16:05:51.000000000 +0100
-@@ -5234,7 +5234,7 @@
+--- ioemu.orig/vl.c    2007-05-03 19:00:14.000000000 +0100
++++ ioemu/vl.c 2007-05-03 19:00:51.000000000 +0100
+@@ -6127,7 +6127,7 @@
             "-S              freeze CPU at startup (use 'c' to start execution)\n"
             "-s              wait gdb connection to port %d\n"
             "-p port         change gdb connection port\n"
@@ -10,8 +10,8 @@ Index: ioemu/vl.c
 +           "-l item1,...    output log to %s (use -d ? for a list of log items)\n"
             "-hdachs c,h,s[,t]  force hard disk 0 physical geometry and the optional BIOS\n"
             "                translation (t=none or lba) (usually qemu can guess them)\n"
-            "-L path         set the directory for the BIOS and VGA BIOS\n"
-@@ -5307,7 +5307,7 @@
+            "-L path         set the directory for the BIOS, VGA BIOS and keymaps\n"
+@@ -6205,7 +6205,7 @@
      QEMU_OPTION_S,
      QEMU_OPTION_s,
      QEMU_OPTION_p,
@@ -20,7 +20,7 @@ Index: ioemu/vl.c
      QEMU_OPTION_hdachs,
      QEMU_OPTION_L,
  #ifdef USE_CODE_COPY
-@@ -5380,7 +5380,7 @@
+@@ -6284,7 +6284,7 @@
      { "S", 0, QEMU_OPTION_S },
      { "s", 0, QEMU_OPTION_s },
      { "p", HAS_ARG, QEMU_OPTION_p },
@@ -29,16 +29,16 @@ Index: ioemu/vl.c
      { "hdachs", HAS_ARG, QEMU_OPTION_hdachs },
      { "L", HAS_ARG, QEMU_OPTION_L },
  #ifdef USE_CODE_COPY
-@@ -5640,6 +5640,8 @@
-     char usb_devices[MAX_USB_CMDLINE][128];
+@@ -6555,6 +6555,8 @@
      int usb_devices_index;
+     int fds[2];
  
 +    char qemu_dm_logfilename[64];
 +
      LIST_INIT (&vm_change_state_head);
  #ifndef _WIN32
      {
-@@ -5719,6 +5721,11 @@
+@@ -6634,6 +6636,11 @@
      nb_nics = 0;
      /* default mac address of the first network interface */
      
@@ -50,7 +50,7 @@ Index: ioemu/vl.c
      optind = 1;
      for(;;) {
          if (optind >= argc)
-@@ -5909,7 +5916,7 @@
+@@ -6827,7 +6834,7 @@
                      exit(1);
                  }
                  break;
index 68291defab5e69c21e5551abea187c4b7ac3dc4c..d71777026ddb4e41cbe03b62a49f206c92f52c8f 100644 (file)
@@ -1,20 +1,20 @@
 Index: ioemu/Makefile.target
 ===================================================================
---- ioemu.orig/Makefile.target 2006-12-08 01:41:11.000000000 +0000
-+++ ioemu/Makefile.target      2006-12-08 01:41:12.000000000 +0000
-@@ -356,7 +356,7 @@
+--- ioemu.orig/Makefile.target 2007-05-03 18:49:10.000000000 +0100
++++ ioemu/Makefile.target      2007-05-03 19:09:54.000000000 +0100
+@@ -387,7 +387,7 @@
  # Hardware support
  VL_OBJS+= ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
  VL_OBJS+= fdc.o mc146818rtc.o serial.o i8254.o pcspk.o pc.o
 -VL_OBJS+= cirrus_vga.o mixeng.o apic.o parallel.o acpi.o piix_pci.o
 +VL_OBJS+= cirrus_vga.o mixeng.o parallel.o acpi.o piix_pci.o
- VL_OBJS+= usb-uhci.o
DEFINES += -DHAS_AUDIO
+ VL_OBJS+= usb-uhci.o smbus_eeprom.o
CPPFLAGS += -DHAS_AUDIO
  endif
 Index: ioemu/hw/pc.c
 ===================================================================
---- ioemu.orig/hw/pc.c 2006-12-08 01:41:12.000000000 +0000
-+++ ioemu/hw/pc.c      2006-12-08 01:41:12.000000000 +0000
+--- ioemu.orig/hw/pc.c 2007-05-03 19:08:19.000000000 +0100
++++ ioemu/hw/pc.c      2007-05-03 19:09:34.000000000 +0100
 @@ -39,7 +39,9 @@
  static fdctrl_t *floppy_controller;
  static RTCState *rtc_state;
@@ -22,12 +22,12 @@ Index: ioemu/hw/pc.c
 +#ifndef CONFIG_DM
  static IOAPICState *ioapic;
 +#endif /* !CONFIG_DM */
+ static PCIDevice *i440fx_state;
  
  static void ioport80_write(void *opaque, uint32_t addr, uint32_t data)
- {
-@@ -640,9 +642,11 @@
+@@ -475,9 +477,11 @@
  #endif /* !CONFIG_DM */
-         register_savevm("cpu", i, 3, cpu_save, cpu_load, env);
+         register_savevm("cpu", i, 4, cpu_save, cpu_load, env);
          qemu_register_reset(main_cpu_reset, env);
 +#ifndef CONFIG_DM
          if (pci_enabled) {
@@ -37,7 +37,7 @@ Index: ioemu/hw/pc.c
      }
  
      /* allocate RAM */
-@@ -789,9 +793,11 @@
+@@ -643,9 +647,11 @@
      register_ioport_read(0x92, 1, 1, ioport92_read, NULL);
      register_ioport_write(0x92, 1, 1, ioport92_write, NULL);
  
index 02229ab6157c36fb635ddbcd6646486f2dfaa3ac..9943ee8903898985975ec03510bbfa357e5563f1 100644 (file)
@@ -1,8 +1,8 @@
 Index: ioemu/hw/pc.c
 ===================================================================
---- ioemu.orig/hw/pc.c 2006-08-06 02:22:11.875161758 +0100
-+++ ioemu/hw/pc.c      2006-08-06 02:22:35.588518336 +0100
-@@ -611,6 +611,8 @@
+--- ioemu.orig/hw/pc.c 2007-05-03 19:09:34.000000000 +0100
++++ ioemu/hw/pc.c      2007-05-03 19:11:08.000000000 +0100
+@@ -446,6 +446,8 @@
      nb_ne2k++;
  }
  
@@ -11,7 +11,7 @@ Index: ioemu/hw/pc.c
  /* PC hardware initialisation */
  static void pc_init1(uint64_t ram_size, int vga_ram_size, int boot_device,
                       DisplayState *ds, const char **fd_filename, int snapshot,
-@@ -618,10 +620,15 @@
+@@ -453,10 +455,15 @@
                       const char *initrd_filename,
                       int pci_enabled)
  {
@@ -19,16 +19,16 @@ Index: ioemu/hw/pc.c
      char buf[1024];
 -    int ret, linux_boot, initrd_size, i;
 +    int ret, initrd_size;
-+#endif
++#endif /* !NOBIOS */
 +    int linux_boot, i;
 +#ifndef NOBIOS
-     unsigned long bios_offset, vga_bios_offset;
+     unsigned long bios_offset, vga_bios_offset, option_rom_offset;
      int bios_size, isa_bios_size;
 +#endif /* !NOBIOS */
      PCIBus *pci_bus;
      int piix3_devfn = -1;
      CPUState *env;
-@@ -654,6 +661,7 @@
+@@ -489,6 +496,7 @@
      cpu_register_physical_memory(0, ram_size, 0);
  #endif
  
@@ -36,7 +36,7 @@ Index: ioemu/hw/pc.c
      /* BIOS load */
      bios_offset = ram_size + vga_ram_size;
      vga_bios_offset = bios_offset + 256 * 1024;
-@@ -682,6 +690,7 @@
+@@ -514,6 +522,7 @@
          snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_FILENAME);
      }
      ret = load_image(buf, phys_ram_base + vga_bios_offset);
@@ -44,7 +44,7 @@ Index: ioemu/hw/pc.c
      
      /* setup basic memory access */
  #ifndef CONFIG_DM             /* HVM domain owns memory */
-@@ -689,6 +698,7 @@
+@@ -521,6 +530,7 @@
                                   vga_bios_offset | IO_MEM_ROM);
  #endif
  
@@ -52,7 +52,7 @@ Index: ioemu/hw/pc.c
      /* map the last 128KB of the BIOS in ISA space */
      isa_bios_size = bios_size;
      if (isa_bios_size > (128 * 1024))
-@@ -701,6 +711,7 @@
+@@ -550,6 +560,7 @@
      /* map all the bios at the top of memory */
      cpu_register_physical_memory((uint32_t)(-bios_size), 
                                   bios_size, bios_offset | IO_MEM_ROM);
index e9d686d02a849a530c63ad9137bdca8023c8aa6f..a6338c08da9196d7aa0e8de8f379cf58cfedfaf3 100755 (executable)
@@ -1,8 +1,8 @@
 Index: ioemu/hw/pci.c
 ===================================================================
---- ioemu.orig/hw/pci.c        2007-05-03 15:20:35.000000000 +0100
-+++ ioemu/hw/pci.c     2007-05-03 15:20:43.000000000 +0100
-@@ -289,6 +289,7 @@
+--- ioemu.orig/hw/pci.c        2007-05-09 14:10:16.000000000 +0100
++++ ioemu/hw/pci.c     2007-05-09 14:10:38.000000000 +0100
+@@ -314,6 +314,7 @@
              case 0x0b:
              case 0x0e:
              case 0x10 ... 0x27: /* base */
@@ -10,7 +10,7 @@ Index: ioemu/hw/pci.c
              case 0x30 ... 0x33: /* rom */
              case 0x3d:
                  can_write = 0;
-@@ -321,6 +322,18 @@
+@@ -346,6 +347,18 @@
              break;
          }
          if (can_write) {
@@ -28,12 +28,12 @@ Index: ioemu/hw/pci.c
 +
              d->config[addr] = val;
          }
-         addr++;
+         if (++addr > 0xff)
 Index: ioemu/hw/rtl8139.c
 ===================================================================
---- ioemu.orig/hw/rtl8139.c    2007-05-03 15:20:35.000000000 +0100
-+++ ioemu/hw/rtl8139.c 2007-05-03 15:20:43.000000000 +0100
-@@ -3424,6 +3424,8 @@
+--- ioemu.orig/hw/rtl8139.c    2007-05-09 14:10:36.000000000 +0100
++++ ioemu/hw/rtl8139.c 2007-05-09 14:10:38.000000000 +0100
+@@ -3432,6 +3432,8 @@
      pci_conf[0x0e] = 0x00; /* header_type */
      pci_conf[0x3d] = 1;    /* interrupt pin 0 */
      pci_conf[0x34] = 0xdc;
@@ -44,9 +44,9 @@ Index: ioemu/hw/rtl8139.c
  
 Index: ioemu/hw/usb-uhci.c
 ===================================================================
---- ioemu.orig/hw/usb-uhci.c   2007-05-03 15:20:35.000000000 +0100
-+++ ioemu/hw/usb-uhci.c        2007-05-03 15:20:43.000000000 +0100
-@@ -704,6 +704,8 @@
+--- ioemu.orig/hw/usb-uhci.c   2007-05-09 14:10:34.000000000 +0100
++++ ioemu/hw/usb-uhci.c        2007-05-09 14:10:38.000000000 +0100
+@@ -832,6 +832,8 @@
      pci_conf[0x0e] = 0x00; // header_type
      pci_conf[0x3d] = 4; // interrupt pin 3
      pci_conf[0x60] = 0x10; // release number
@@ -57,9 +57,9 @@ Index: ioemu/hw/usb-uhci.c
          qemu_register_usb_port(&s->ports[i].port, s, i, uhci_attach);
 Index: ioemu/vl.h
 ===================================================================
---- ioemu.orig/vl.h    2007-05-03 15:20:43.000000000 +0100
-+++ ioemu/vl.h 2007-05-03 15:20:43.000000000 +0100
-@@ -650,8 +650,11 @@
+--- ioemu.orig/vl.h    2007-05-09 14:10:38.000000000 +0100
++++ ioemu/vl.h 2007-05-09 14:10:38.000000000 +0100
+@@ -779,8 +779,11 @@
  #define PCI_MAX_LAT           0x3f    /* 8 bits */
  
  struct PCIDevice {
index 65e9011861a5fcb1ceb479255ffbf4453fec1254..98974b26597d7f6204c88b59f1ee4a225de7b7e1 100644 (file)
@@ -1,8 +1,8 @@
 Index: ioemu/hw/cirrus_vga.c
 ===================================================================
---- ioemu.orig/hw/cirrus_vga.c 2007-05-03 15:06:41.000000000 +0100
-+++ ioemu/hw/cirrus_vga.c      2007-05-03 15:07:16.000000000 +0100
-@@ -3339,6 +3339,10 @@
+--- ioemu.orig/hw/cirrus_vga.c 2007-05-03 19:16:30.000000000 +0100
++++ ioemu/hw/cirrus_vga.c      2007-05-03 20:36:50.000000000 +0100
+@@ -3354,6 +3354,10 @@
      pci_conf[0x0a] = PCI_CLASS_SUB_VGA;
      pci_conf[0x0b] = PCI_CLASS_BASE_DISPLAY;
      pci_conf[0x0e] = PCI_CLASS_HEADERTYPE_00h;
@@ -15,9 +15,9 @@ Index: ioemu/hw/cirrus_vga.c
      s = &d->cirrus_vga;
 Index: ioemu/hw/rtl8139.c
 ===================================================================
---- ioemu.orig/hw/rtl8139.c    2007-05-03 15:07:16.000000000 +0100
-+++ ioemu/hw/rtl8139.c 2007-05-03 15:07:16.000000000 +0100
-@@ -3424,8 +3424,10 @@
+--- ioemu.orig/hw/rtl8139.c    2007-05-03 20:36:46.000000000 +0100
++++ ioemu/hw/rtl8139.c 2007-05-03 20:36:50.000000000 +0100
+@@ -3432,8 +3432,10 @@
      pci_conf[0x0e] = 0x00; /* header_type */
      pci_conf[0x3d] = 1;    /* interrupt pin 0 */
      pci_conf[0x34] = 0xdc;
@@ -32,9 +32,9 @@ Index: ioemu/hw/rtl8139.c
  
 Index: ioemu/hw/ide.c
 ===================================================================
---- ioemu.orig/hw/ide.c        2007-05-03 15:07:16.000000000 +0100
-+++ ioemu/hw/ide.c     2007-05-03 15:07:16.000000000 +0100
-@@ -2763,6 +2763,10 @@
+--- ioemu.orig/hw/ide.c        2007-05-03 20:35:19.000000000 +0100
++++ ioemu/hw/ide.c     2007-05-03 20:36:50.000000000 +0100
+@@ -2747,6 +2747,10 @@
      pci_conf[0x0a] = 0x01; // class_sub = PCI_IDE
      pci_conf[0x0b] = 0x01; // class_base = PCI_mass_storage
      pci_conf[0x0e] = 0x00; // header_type
@@ -43,5 +43,5 @@ Index: ioemu/hw/ide.c
 +    pci_conf[0x2e] = 0x01; /* subsystem device */
 +    pci_conf[0x2f] = 0x00;
  
-     pci_register_io_region((PCIDevice *)d, 4, 0x10, 
-                            PCI_ADDRESS_SPACE_IO, bmdma_map);
+     piix3_reset(d);
index 0e74d91ec51e6c2e2d7878f6f1557dbb509a92be..1c5a41f399b295bbc24b60d67e2209e2fdcd6d50 100644 (file)
@@ -13,21 +13,21 @@ Signed-off-by: Keir Fraser <keir@xensource.com>
 
 Index: ioemu/vl.c
 ===================================================================
---- ioemu.orig/vl.c    2007-05-03 10:09:02.000000000 +0100
-+++ ioemu/vl.c 2007-05-03 10:09:02.000000000 +0100
-@@ -1740,7 +1740,7 @@
+--- ioemu.orig/vl.c    2007-05-03 20:38:49.000000000 +0100
++++ ioemu/vl.c 2007-05-03 20:39:06.000000000 +0100
+@@ -1874,7 +1874,7 @@
  
      tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
                            |INLCR|IGNCR|ICRNL|IXON);
 -    tty.c_oflag |= OPOST;
 +    tty.c_oflag &= ~OPOST; /* no output mangling of raw serial stream */
      tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN|ISIG);
-     tty.c_cflag &= ~(CSIZE|PARENB|PARODD|CRTSCTS);
+     tty.c_cflag &= ~(CSIZE|PARENB|PARODD|CRTSCTS|CSTOPB);
      switch(data_bits) {
 Index: ioemu/hw/serial.c
 ===================================================================
---- ioemu.orig/hw/serial.c     2007-05-03 10:09:02.000000000 +0100
-+++ ioemu/hw/serial.c  2007-05-03 10:09:02.000000000 +0100
+--- ioemu.orig/hw/serial.c     2007-05-03 20:36:58.000000000 +0100
++++ ioemu/hw/serial.c  2007-05-03 20:39:06.000000000 +0100
 @@ -73,6 +73,11 @@
  #define UART_LSR_OE   0x02    /* Overrun error indicator */
  #define UART_LSR_DR   0x01    /* Receiver data ready */
@@ -38,7 +38,7 @@ Index: ioemu/hw/serial.c
 +#define WRITE_MAX_TOTAL_RETRIES 10
 +
  struct SerialState {
-     uint8_t divider;
+     uint16_t divider;
      uint8_t rbr; /* receive register */
 @@ -93,6 +98,19 @@
      int last_break_enable;
@@ -115,19 +115,19 @@ Index: ioemu/hw/serial.c
          }
          break;
      case 1:
-@@ -424,6 +466,7 @@
+@@ -427,6 +469,7 @@
      s->lsr = UART_LSR_TEMT | UART_LSR_THRE;
      s->iir = UART_IIR_NO_INT;
      s->msr = UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS;
 +    s->write_retry_timer = qemu_new_timer(vm_clock, serial_chr_write, s);
  
-     register_savevm("serial", base, 1, serial_save, serial_load, s);
+     register_savevm("serial", base, 2, serial_save, serial_load, s);
  
-@@ -511,6 +554,7 @@
+@@ -514,6 +557,7 @@
      s->msr = UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS;
      s->base = base;
      s->it_shift = it_shift;
 +    s->write_retry_timer = qemu_new_timer(vm_clock, serial_chr_write, s);
  
-     register_savevm("serial", base, 1, serial_save, serial_load, s);
+     register_savevm("serial", base, 2, serial_save, serial_load, s);
  
index dfa6039b93675d273c25d0fd9cfd63ae3eabc6ce..2bdfe01de48a7f47daa469fccd4c0bd9f23153c8 100644 (file)
@@ -1,41 +1,41 @@
 Index: ioemu/vl.c
 ===================================================================
---- ioemu.orig/vl.c    2007-05-03 10:07:47.000000000 +0100
-+++ ioemu/vl.c 2007-05-03 10:07:52.000000000 +0100
-@@ -159,6 +159,8 @@
- int acpi_enabled = 1;
- int fd_bootchk = 1;
+--- ioemu.orig/vl.c    2007-05-03 19:09:15.000000000 +0100
++++ ioemu/vl.c 2007-05-03 19:09:18.000000000 +0100
+@@ -176,6 +176,8 @@
+ int semihosting_enabled = 0;
+ int autostart = 1;
  
 +extern int vcpus;
 +
  int xc_handle;
  
  char domain_name[1024] = { 'H','V', 'M', 'X', 'E', 'N', '-'};
-@@ -5173,6 +5175,7 @@
+@@ -6065,6 +6067,7 @@
             "-m megs         set virtual RAM size to megs MB [default=%d]\n"
             "-smp n          set the number of CPUs to 'n' [default=1]\n"
             "-nographic      disable graphical output and redirect serial I/Os to console\n"
 +           "-vcpus          set CPU number of guest platform\n"
  #ifndef _WIN32
-          "-k language     use keyboard layout (for example \"fr\" for French)\n"
+            "-k language     use keyboard layout (for example \"fr\" for French)\n"
  #endif
-@@ -5343,6 +5346,7 @@
-     QEMU_OPTION_no_acpi,
+@@ -6246,6 +6249,7 @@
+     QEMU_OPTION_semihosting
+     ,
      QEMU_OPTION_d,
 +    QEMU_OPTION_vcpus,
  };
  
  typedef struct QEMUOption {
-@@ -5424,6 +5428,7 @@
-     { "no-acpi", 0, QEMU_OPTION_no_acpi },
+@@ -6337,6 +6341,7 @@
+ #endif
      
      { "d", HAS_ARG, QEMU_OPTION_d },
 +    { "vcpus", 1, QEMU_OPTION_vcpus },
      { NULL },
  };
  
-@@ -6092,6 +6097,10 @@
+@@ -7028,6 +7033,10 @@
                  domid = atoi(optarg);
                  fprintf(logfile, "domid: %d\n", domid);
                  break;
index 061cdd1cabc2d3c19e100a9e7b67fa2939f759e6..d5ced253ff5d8065950ca2c1439f4af007e13d05 100644 (file)
@@ -1,8 +1,8 @@
 Index: ioemu/Makefile.target
 ===================================================================
---- ioemu.orig/Makefile.target 2007-05-03 14:53:03.000000000 +0100
-+++ ioemu/Makefile.target      2007-05-03 14:53:58.000000000 +0100
-@@ -62,6 +62,8 @@
+--- ioemu.orig/Makefile.target 2007-05-09 14:08:42.000000000 +0100
++++ ioemu/Makefile.target      2007-05-09 14:09:10.000000000 +0100
+@@ -65,6 +65,8 @@
  QEMU_SYSTEM=qemu-fast
  endif
  
@@ -11,7 +11,7 @@ Index: ioemu/Makefile.target
  ifdef CONFIG_USER_ONLY
  PROGS=$(QEMU_USER)
  else
-@@ -292,6 +294,9 @@
+@@ -321,6 +323,9 @@
  OBJS+=gdbstub.o
  endif
  
@@ -21,22 +21,22 @@ Index: ioemu/Makefile.target
  all: $(PROGS)
  
  $(QEMU_USER): $(OBJS)
-@@ -350,7 +355,7 @@
+@@ -381,7 +386,7 @@
  ifeq ($(TARGET_BASE_ARCH), i386)
  # Hardware support
  VL_OBJS+= ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
 -VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pcspk.o pc.o
 +VL_OBJS+= fdc.o mc146818rtc.o serial.o i8254.o pcspk.o pc.o
  VL_OBJS+= cirrus_vga.o mixeng.o apic.o parallel.o acpi.o piix_pci.o
- VL_OBJS+= usb-uhci.o
DEFINES += -DHAS_AUDIO
+ VL_OBJS+= usb-uhci.o smbus_eeprom.o
CPPFLAGS += -DHAS_AUDIO
 Index: ioemu/configure
 ===================================================================
---- ioemu.orig/configure       2007-05-03 14:53:03.000000000 +0100
-+++ ioemu/configure    2007-05-03 14:53:57.000000000 +0100
-@@ -373,6 +373,8 @@
-     if [ "$user" = "yes" ] ; then
-         target_list="i386-user arm-user armeb-user sparc-user ppc-user mips-user mipsel-user $target_list"
+--- ioemu.orig/configure       2007-05-09 14:08:42.000000000 +0100
++++ ioemu/configure    2007-05-09 14:09:10.000000000 +0100
+@@ -426,6 +426,8 @@
+     if [ "$darwin_user" = "yes" ] ; then
+         target_list="i386-darwin-user ppc-darwin-user $target_list"
      fi
 +# the i386-dm target
 +    target_list="i386-dm"
@@ -45,33 +45,33 @@ Index: ioemu/configure
  fi
 Index: ioemu/monitor.c
 ===================================================================
---- ioemu.orig/monitor.c       2007-05-03 14:53:03.000000000 +0100
-+++ ioemu/monitor.c    2007-05-03 14:53:58.000000000 +0100
-@@ -1262,6 +1262,10 @@
-       "", "show profiling information", },
-     { "capture", "", do_info_capture,
-       "show capture information" },
+--- ioemu.orig/monitor.c       2007-05-09 14:08:59.000000000 +0100
++++ ioemu/monitor.c    2007-05-09 14:09:10.000000000 +0100
+@@ -1325,6 +1325,10 @@
+       "", "show which guest mouse is receiving events" },
+     { "vnc", "", do_info_vnc,
+       "", "show the vnc server status"},
 +#ifdef CONFIG_DM
 +    { "hvmiopage", "", sp_info,
-+      "", "show HVM device model shared page info", },
++      "", "show HVM device model shared page info" },
 +#endif /* CONFIG_DM */
      { NULL, NULL, },
  };
  
 Index: ioemu/vl.c
 ===================================================================
---- ioemu.orig/vl.c    2007-05-03 14:53:03.000000000 +0100
-+++ ioemu/vl.c 2007-05-03 14:53:59.000000000 +0100
-@@ -87,7 +87,7 @@
+--- ioemu.orig/vl.c    2007-05-09 14:08:42.000000000 +0100
++++ ioemu/vl.c 2007-05-09 14:09:10.000000000 +0100
+@@ -88,7 +88,7 @@
  
  #include "exec-all.h"
  
 -#define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup"
 +#define DEFAULT_NETWORK_SCRIPT "/etc/xen/qemu-ifup"
- //#define DEBUG_UNUSED_IOPORT
- //#define DEBUG_IOPORT
-@@ -4918,7 +4918,7 @@
+ #ifdef __sun__
+ #define SMBD_COMMAND "/usr/sfw/sbin/smbd"
+ #else
+@@ -5805,7 +5805,7 @@
  
  static QEMUResetEntry *first_reset_entry;
  static int reset_requested;
@@ -80,7 +80,7 @@ Index: ioemu/vl.c
  static int powerdown_requested;
  
  void qemu_register_reset(QEMUResetHandler *func, void *opaque)
-@@ -5067,6 +5067,7 @@
+@@ -5957,6 +5957,7 @@
                      qemu_get_clock(rt_clock));
  }
  
@@ -88,7 +88,7 @@ Index: ioemu/vl.c
  static CPUState *cur_cpu;
  
  int main_loop(void)
-@@ -5141,6 +5142,7 @@
+@@ -6031,6 +6032,7 @@
      cpu_disable_ticks();
      return ret;
  }
@@ -98,8 +98,8 @@ Index: ioemu/vl.c
  {
 Index: ioemu/vl.h
 ===================================================================
---- ioemu.orig/vl.h    2007-05-03 14:52:58.000000000 +0100
-+++ ioemu/vl.h 2007-05-03 14:53:59.000000000 +0100
+--- ioemu.orig/vl.h    2007-05-09 14:08:42.000000000 +0100
++++ ioemu/vl.h 2007-05-09 14:09:10.000000000 +0100
 @@ -37,6 +37,8 @@
  #include <unistd.h>
  #include <fcntl.h>
@@ -109,7 +109,7 @@ Index: ioemu/vl.h
  
  #ifndef O_LARGEFILE
  #define O_LARGEFILE 0
-@@ -139,6 +141,11 @@
+@@ -144,6 +146,11 @@
  
  void main_loop_wait(int timeout);
  
@@ -121,7 +121,7 @@ Index: ioemu/vl.h
  extern int ram_size;
  extern int bios_size;
  extern int rtc_utc;
-@@ -873,6 +880,7 @@
+@@ -1023,6 +1030,7 @@
  uint32_t pic_intack_read(PicState2 *s);
  void pic_info(void);
  void irq_info(void);
@@ -132,7 +132,7 @@ Index: ioemu/vl.h
 Index: ioemu/target-i386-dm/cpu.h
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ ioemu/target-i386-dm/cpu.h 2007-05-03 14:53:58.000000000 +0100
++++ ioemu/target-i386-dm/cpu.h 2007-05-09 14:09:10.000000000 +0100
 @@ -0,0 +1,84 @@
 +/*
 + * i386 virtual CPU header
@@ -221,7 +221,7 @@ Index: ioemu/target-i386-dm/cpu.h
 Index: ioemu/target-i386-dm/exec-dm.c
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ ioemu/target-i386-dm/exec-dm.c     2007-05-03 14:53:56.000000000 +0100
++++ ioemu/target-i386-dm/exec-dm.c     2007-05-09 14:09:10.000000000 +0100
 @@ -0,0 +1,540 @@
 +/*
 + *  virtual page mapping and translated block handling
@@ -766,7 +766,7 @@ Index: ioemu/target-i386-dm/exec-dm.c
 Index: ioemu/target-i386-dm/helper2.c
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ ioemu/target-i386-dm/helper2.c     2007-05-03 14:54:46.000000000 +0100
++++ ioemu/target-i386-dm/helper2.c     2007-05-09 14:09:10.000000000 +0100
 @@ -0,0 +1,542 @@
 +/*
 + *  i386 helpers (without register variable usage)
@@ -1313,7 +1313,7 @@ Index: ioemu/target-i386-dm/helper2.c
 Index: ioemu/target-i386-dm/i8259-dm.c
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ ioemu/target-i386-dm/i8259-dm.c    2007-05-03 14:53:57.000000000 +0100
++++ ioemu/target-i386-dm/i8259-dm.c    2007-05-09 14:09:10.000000000 +0100
 @@ -0,0 +1,67 @@
 +/* Xen 8259 stub for interrupt controller emulation
 + * 
@@ -1385,7 +1385,7 @@ Index: ioemu/target-i386-dm/i8259-dm.c
 Index: ioemu/target-i386-dm/qemu-dm.debug
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ ioemu/target-i386-dm/qemu-dm.debug 2007-05-03 14:53:03.000000000 +0100
++++ ioemu/target-i386-dm/qemu-dm.debug 2007-05-09 14:09:10.000000000 +0100
 @@ -0,0 +1,10 @@
 +#!/bin/sh
 +
@@ -1400,7 +1400,7 @@ Index: ioemu/target-i386-dm/qemu-dm.debug
 Index: ioemu/target-i386-dm/qemu-ifup
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ ioemu/target-i386-dm/qemu-ifup     2007-05-03 14:53:03.000000000 +0100
++++ ioemu/target-i386-dm/qemu-ifup     2007-05-09 14:09:10.000000000 +0100
 @@ -0,0 +1,9 @@
 +#!/bin/sh
 +
index 6f7409bfbddde3729b9a836560391631b80f9138..cfb659c7466fb6b8af3f8451300ca6bd9070b9df 100644 (file)
@@ -1,8 +1,8 @@
 Index: ioemu/vl.c
 ===================================================================
---- ioemu.orig/vl.c    2007-05-03 10:07:52.000000000 +0100
-+++ ioemu/vl.c 2007-05-03 10:07:52.000000000 +0100
-@@ -825,6 +825,16 @@
+--- ioemu.orig/vl.c    2007-05-03 19:11:56.000000000 +0100
++++ ioemu/vl.c 2007-05-03 19:11:59.000000000 +0100
+@@ -912,6 +912,16 @@
      }
  }
  
@@ -19,7 +19,7 @@ Index: ioemu/vl.c
  static void timer_save(QEMUFile *f, void *opaque)
  {
      if (cpu_ticks_enabled) {
-@@ -941,6 +951,8 @@
+@@ -1032,6 +1042,8 @@
  
  #endif /* !defined(_WIN32) */
  
@@ -28,7 +28,7 @@ Index: ioemu/vl.c
  static void init_timer_alarm(void)
  {
  #ifdef _WIN32
-@@ -972,12 +984,15 @@
+@@ -1063,12 +1075,15 @@
      pit_min_timer_count = ((uint64_t)10000 * PIT_FREQ) / 1000000;
  #else
      {
@@ -44,7 +44,7 @@ Index: ioemu/vl.c
          /* timer signal */
          sigfillset(&act.sa_mask);
         act.sa_flags = 0;
-@@ -1023,6 +1038,7 @@
+@@ -1114,6 +1129,7 @@
              pit_min_timer_count = ((uint64_t)itv.it_interval.tv_usec * 
                                     PIT_FREQ) / 1000000;
          }
index 735375fb0f7f327d9324e1f4a9da44b957386421..0adfd32f4c5c7a81fc23ab0d8a56e4b0e7044c12 100644 (file)
@@ -1,8 +1,8 @@
 Index: ioemu/hw/ide.c
 ===================================================================
---- ioemu.orig/hw/ide.c        2007-05-03 15:07:15.000000000 +0100
-+++ ioemu/hw/ide.c     2007-05-03 15:07:16.000000000 +0100
-@@ -305,6 +305,7 @@
+--- ioemu.orig/hw/ide.c        2007-05-03 20:31:55.000000000 +0100
++++ ioemu/hw/ide.c     2007-05-03 20:35:19.000000000 +0100
+@@ -306,6 +306,7 @@
      PCIDevice *pci_dev;
      struct BMDMAState *bmdma;
      int drive_serial;
@@ -10,7 +10,7 @@ Index: ioemu/hw/ide.c
      /* ide regs */
      uint8_t feature;
      uint8_t error;
-@@ -947,6 +948,9 @@
+@@ -921,6 +922,9 @@
      }
      ide_set_sector(s, sector_num + n);
      
@@ -20,18 +20,7 @@ Index: ioemu/hw/ide.c
  #ifdef TARGET_I386
      if (win2k_install_hack && ((++s->irq_count % 16) == 0)) {
          /* It seems there is a bug in the Windows 2000 installer HDD
-@@ -1021,6 +1025,10 @@
-         transfer_size -= len;
-         phys_addr += len;
-     }
-+    /* Ensure the data hit disk before telling the guest OS so. */
-+    if (!s->write_cache)
-+        bdrv_flush(s->bs);
-+
-     return transfer_size1 - transfer_size;
- }
-@@ -1831,7 +1839,15 @@
+@@ -1849,7 +1853,15 @@
              /* XXX: valid for CDROM ? */
              switch(s->feature) {
              case 0x02: /* write cache enable */
@@ -47,7 +36,7 @@ Index: ioemu/hw/ide.c
              case 0xaa: /* read look-ahead enable */
              case 0x55: /* read look-ahead disable */
                  s->status = READY_STAT | SEEK_STAT;
-@@ -2254,6 +2270,7 @@
+@@ -2282,6 +2294,7 @@
          s->irq = irq;
          s->sector_write_timer = qemu_new_timer(vm_clock, 
                                                 ide_sector_write_timer_cb, s);
index a4f4c80b8093047bffd01c86db37a817b95d5ee6..d3a49f542a12afe52bad82224c1139f195b17364 100644 (file)
@@ -7,61 +7,13 @@ Signed-off-by: Keir Fraser <keir@xensource.com>
 
 Index: ioemu/target-i386-dm/piix_pci-dm.c
 ===================================================================
---- ioemu.orig/target-i386-dm/piix_pci-dm.c    2006-12-08 18:22:35.000000000 +0000
-+++ ioemu/target-i386-dm/piix_pci-dm.c 2006-12-08 18:22:50.000000000 +0000
-@@ -84,12 +84,6 @@
- static PCIDevice *piix3_dev;
--static int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
--{
--    /* This is the barber's pole mapping used by Xen. */
--    return (irq_num + (pci_dev->devfn >> 3)) & 3;
--}
--
- static void piix3_write_config(PCIDevice *d, 
-                                uint32_t address, uint32_t val, int len)
- {
-@@ -114,12 +108,9 @@
-     uint8_t *pci_conf = d->config;
-     pci_conf[0x04] = 0x07; // master, memory and I/O
--    pci_conf[0x05] = 0x00;
--    pci_conf[0x06] = 0x00;
-     pci_conf[0x07] = 0x02; // PCI_status_devsel_medium
-     pci_conf[0x4c] = 0x4d;
-     pci_conf[0x4e] = 0x03;
--    pci_conf[0x4f] = 0x00;
-     pci_conf[0x60] = 0x80;
-     pci_conf[0x61] = 0x80;
-     pci_conf[0x62] = 0x80;
-@@ -129,22 +120,9 @@
-     pci_conf[0x76] = 0x0c;
-     pci_conf[0x77] = 0x0c;
-     pci_conf[0x78] = 0x02;
--    pci_conf[0x79] = 0x00;
--    pci_conf[0x80] = 0x00;
--    pci_conf[0x82] = 0x00;
-     pci_conf[0xa0] = 0x08;
-     pci_conf[0xa0] = 0x08;
--    pci_conf[0xa2] = 0x00;
--    pci_conf[0xa3] = 0x00;
--    pci_conf[0xa4] = 0x00;
--    pci_conf[0xa5] = 0x00;
--    pci_conf[0xa6] = 0x00;
--    pci_conf[0xa7] = 0x00;
-     pci_conf[0xa8] = 0x0f;
--    pci_conf[0xaa] = 0x00;
--    pci_conf[0xab] = 0x00;
--    pci_conf[0xac] = 0x00;
--    pci_conf[0xae] = 0x00;
- }
- int piix3_init(PCIBus *bus)
-@@ -171,227 +149,4 @@
+--- ioemu.orig/target-i386-dm/piix_pci-dm.c    2007-05-09 14:07:46.000000000 +0100
++++ ioemu/target-i386-dm/piix_pci-dm.c 2007-05-09 14:07:56.000000000 +0100
+@@ -220,228 +220,3 @@
+     piix3_reset(d);
      return d->devfn;
  }
+-
 -/***********************************************************/
 -/* XXX: the following should be moved to the PC BIOS */
 -
@@ -286,4 +238,3 @@ Index: ioemu/target-i386-dm/piix_pci-dm.c
 -    pci_for_each_device(pci_bios_init_device);
 -}
 -
-+void pci_bios_init(void) {}
index a360ddbc498074164b5a1a8454dbedbd2719ea43..2ff2b208b9f7c74d4e15e8c47379c1fc4bd1260c 100644 (file)
@@ -15,8 +15,8 @@ Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
 
 Index: ioemu/hw/rtl8139.c
 ===================================================================
---- ioemu.orig/hw/rtl8139.c    2006-12-08 18:21:36.000000000 +0000
-+++ ioemu/hw/rtl8139.c 2006-12-08 18:22:22.000000000 +0000
+--- ioemu.orig/hw/rtl8139.c    2007-05-03 20:36:50.000000000 +0100
++++ ioemu/hw/rtl8139.c 2007-05-03 20:39:45.000000000 +0100
 @@ -1999,12 +1999,12 @@
          DEBUG_PRINT(("RTL8139: +++ C+ mode transmission buffer allocated space %d\n", s->cplus_txbuffer_len));
      }
index 8855eda92323f54d6ae0ed63f86cbe6f0d94d0d8..802e4a07d816eb5f774d0699de4a87e8f2c5d24d 100644 (file)
@@ -1,17 +1,17 @@
 Index: ioemu/vl.c
 ===================================================================
---- ioemu.orig/vl.c    2007-05-03 15:20:45.000000000 +0100
-+++ ioemu/vl.c 2007-05-03 15:20:45.000000000 +0100
-@@ -116,7 +116,7 @@
- void *ioport_opaque[MAX_IOPORTS];
- IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS];
+--- ioemu.orig/vl.c    2007-05-09 13:49:10.000000000 +0100
++++ ioemu/vl.c 2007-05-09 13:49:10.000000000 +0100
+@@ -124,7 +124,7 @@
  IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS];
--BlockDriverState *bs_table[MAX_DISKS], *fd_table[MAX_FD];
-+BlockDriverState *bs_table[MAX_DISKS + MAX_SCSI_DISKS], *fd_table[MAX_FD];
+ /* Note: bs_table[MAX_DISKS] is a dummy block driver if none available
+    to store the VM snapshots */
+-BlockDriverState *bs_table[MAX_DISKS + 1], *fd_table[MAX_FD];
++BlockDriverState *bs_table[MAX_DISKS + MAX_SCSI_DISKS + 1], *fd_table[MAX_FD];
+ /* point to the block driver where the snapshots are managed */
+ BlockDriverState *bs_snapshots;
  int vga_ram_size;
- int bios_size;
- static DisplayState display_state;
-@@ -1396,7 +1396,7 @@
+@@ -1529,7 +1529,7 @@
          case 's': 
              {
                  int i;
@@ -20,7 +20,7 @@ Index: ioemu/vl.c
                      if (bs_table[i])
                          bdrv_commit(bs_table[i]);
                  }
-@@ -6057,7 +6057,7 @@
+@@ -6969,7 +6969,7 @@
      int snapshot, linux_boot;
      const char *initrd_filename;
  #ifndef CONFIG_DM
@@ -29,7 +29,7 @@ Index: ioemu/vl.c
  #endif /* !CONFIG_DM */
      const char *fd_filename[MAX_FD];
      const char *kernel_filename, *kernel_cmdline;
-@@ -6126,7 +6126,7 @@
+@@ -7038,7 +7038,7 @@
      for(i = 0; i < MAX_FD; i++)
          fd_filename[i] = NULL;
  #ifndef CONFIG_DM
@@ -38,7 +38,7 @@ Index: ioemu/vl.c
          hd_filename[i] = NULL;
  #endif /* !CONFIG_DM */
      ram_size = DEFAULT_RAM_SIZE * 1024 * 1024;
-@@ -6724,7 +6724,7 @@
+@@ -7737,7 +7737,7 @@
      }
  
      /* open the virtual block devices */
@@ -49,32 +49,32 @@ Index: ioemu/vl.c
                  char buf[64];
 Index: ioemu/vl.h
 ===================================================================
---- ioemu.orig/vl.h    2007-05-03 15:20:45.000000000 +0100
-+++ ioemu/vl.h 2007-05-03 15:20:45.000000000 +0100
-@@ -818,8 +818,9 @@
+--- ioemu.orig/vl.h    2007-05-09 13:49:10.000000000 +0100
++++ ioemu/vl.h 2007-05-09 13:51:28.000000000 +0100
+@@ -965,8 +965,9 @@
  
  /* ide.c */
  #define MAX_DISKS 4
 +#define MAX_SCSI_DISKS 7
  
--extern BlockDriverState *bs_table[MAX_DISKS];
-+extern BlockDriverState *bs_table[MAX_DISKS + MAX_SCSI_DISKS];
+-extern BlockDriverState *bs_table[MAX_DISKS + 1];
++extern BlockDriverState *bs_table[MAX_DISKS + MAX_SCSI_DISKS + 1];
  
  void isa_ide_init(int iobase, int iobase2, int irq,
                    BlockDriverState *hd0, BlockDriverState *hd1);
 Index: ioemu/hw/pc.c
 ===================================================================
---- ioemu.orig/hw/pc.c 2007-05-03 15:20:44.000000000 +0100
-+++ ioemu/hw/pc.c      2007-05-03 15:20:45.000000000 +0100
-@@ -902,7 +902,6 @@
-     if (pci_enabled && acpi_enabled) {
-         piix4_pm_init(pci_bus, piix3_devfn + 3);
+--- ioemu.orig/hw/pc.c 2007-05-09 13:49:09.000000000 +0100
++++ ioemu/hw/pc.c      2007-05-09 13:49:10.000000000 +0100
+@@ -761,7 +761,6 @@
+             piix4_smbus_register_device(eeprom, 0x50 + i);
+         }
      }
 -#endif /* !CONFIG_DM */
- #if 0
-     /* ??? Need to figure out some way for the user to
-@@ -921,6 +920,18 @@
+     
+     if (i440fx_state) {
+         i440fx_init_memory_mappings(i440fx_state);
+@@ -783,6 +782,18 @@
          lsi_scsi_attach(scsi, bdrv, -1);
      }
  #endif
@@ -90,13 +90,13 @@ Index: ioemu/hw/pc.c
 +        }
 +    }
 +#endif /* !CONFIG_DM */
-     /* must be done after all PCI devices are instanciated */
-     /* XXX: should be done in the Bochs BIOS */
-     if (pci_enabled) {
+ }
+ static void pc_init_pci(uint64_t ram_size, int vga_ram_size, char *boot_device,
 Index: ioemu/xenstore.c
 ===================================================================
---- ioemu.orig/xenstore.c      2007-05-03 15:20:45.000000000 +0100
-+++ ioemu/xenstore.c   2007-05-03 15:20:45.000000000 +0100
+--- ioemu.orig/xenstore.c      2007-05-09 13:49:10.000000000 +0100
++++ ioemu/xenstore.c   2007-05-09 13:49:10.000000000 +0100
 @@ -18,7 +18,7 @@
  #include <fcntl.h>
  
@@ -163,22 +163,22 @@ Index: ioemu/xenstore.c
          }
 Index: ioemu/monitor.c
 ===================================================================
---- ioemu.orig/monitor.c       2007-05-03 15:18:43.000000000 +0100
-+++ ioemu/monitor.c    2007-05-03 15:20:45.000000000 +0100
-@@ -180,7 +180,7 @@
- {
-     int i;
+--- ioemu.orig/monitor.c       2007-05-09 13:48:54.000000000 +0100
++++ ioemu/monitor.c    2007-05-09 13:49:19.000000000 +0100
+@@ -209,7 +209,7 @@
+     int i, all_devices;
+     
+     all_devices = !strcmp(device, "all");
 -    for (i = 0; i < MAX_DISKS; i++) {
 +    for (i = 0; i < MAX_DISKS + MAX_SCSI_DISKS; i++) {
          if (bs_table[i]) {
-             bdrv_commit(bs_table[i]);
-         }
+             if (all_devices || 
+                 !strcmp(bdrv_get_device_name(bs_table[i]), device))
 Index: ioemu/hw/lsi53c895a.c
 ===================================================================
---- ioemu.orig/hw/lsi53c895a.c 2007-05-03 15:18:43.000000000 +0100
-+++ ioemu/hw/lsi53c895a.c      2007-05-03 15:20:45.000000000 +0100
-@@ -1071,8 +1071,13 @@
+--- ioemu.orig/hw/lsi53c895a.c 2007-05-09 13:48:54.000000000 +0100
++++ ioemu/hw/lsi53c895a.c      2007-05-09 13:49:10.000000000 +0100
+@@ -1351,8 +1351,13 @@
          shift = (offset & 3) * 8;
          return (s->scratch[n] >> shift) & 0xff;
      }
index 220f68d3a4eb1c7fa436afb3776fdb12b58657a1..a8bbf68d0c8c746bca93e35d05ecbc91f8a1308a 100644 (file)
@@ -1,8 +1,8 @@
 Index: ioemu/vl.c
 ===================================================================
---- ioemu.orig/vl.c    2007-05-03 10:07:53.000000000 +0100
-+++ ioemu/vl.c 2007-05-03 10:07:53.000000000 +0100
-@@ -1176,19 +1176,34 @@
+--- ioemu.orig/vl.c    2007-05-03 19:15:06.000000000 +0100
++++ ioemu/vl.c 2007-05-03 19:15:58.000000000 +0100
+@@ -1298,19 +1298,34 @@
  
  static int unix_write(int fd, const uint8_t *buf, int len1)
  {
index 17eac339512d4638037ba772299baa0f6636d2e6..755bbbf9809e31acde28fb1bb8c3fefcfbb2b96a 100644 (file)
@@ -7,8 +7,10 @@ grub's boot menu from hammering dom0.
 
 Signed-off-by: Steven Smith <sos22@cam.ac.uk>
 
---- ioemu/hw/serial.c  Mon Sep 25 16:31:02 2006 +0100
-+++ ioemu/hw/serial.c  Mon Sep 25 17:27:18 2006 +0100
+Index: ioemu/hw/serial.c
+===================================================================
+--- ioemu.orig/hw/serial.c     2007-05-03 18:18:01.000000000 +0100
++++ ioemu/hw/serial.c  2007-05-03 20:36:58.000000000 +0100
 @@ -22,6 +22,9 @@
   * THE SOFTWARE.
   */
@@ -19,12 +21,10 @@ Signed-off-by: Steven Smith <sos22@cam.ac.uk>
  
  //#define DEBUG_SERIAL
  
-@@ -138,6 +141,67 @@ static void serial_update_parameters(Ser
-     printf("speed=%d parity=%c data=%d stop=%d\n", 
-            speed, parity, data_bits, stop_bits);
+@@ -140,6 +143,67 @@
  #endif
-+}
-+
+ }
 +/* Rate limit serial requests so that e.g. grub on a serial console
 +   doesn't kill dom0.  Simple token bucket.  If we get some actual
 +   data from the user, instantly refil the bucket. */
@@ -84,10 +84,12 @@ Signed-off-by: Steven Smith <sos22@cam.ac.uk>
 +      tokens_avail = generated;
 +    }
 +    tokens_avail--;
- }
++}
++
  static void serial_ioport_write(void *opaque, uint32_t addr, uint32_t val)
-@@ -245,9 +309,11 @@ static uint32_t serial_ioport_read(void 
+ {
+     SerialState *s = opaque;
+@@ -245,9 +309,11 @@
          ret = s->mcr;
          break;
      case 5:
@@ -99,7 +101,7 @@ Signed-off-by: Steven Smith <sos22@cam.ac.uk>
          if (s->mcr & UART_MCR_LOOP) {
              /* in loopback, the modem output pins are connected to the
                 inputs */
-@@ -296,12 +362,14 @@ static void serial_receive1(void *opaque
+@@ -296,12 +362,14 @@
  static void serial_receive1(void *opaque, const uint8_t *buf, int size)
  {
      SerialState *s = opaque;
index e5a07582c55385ee4c364ae2ceaf6f443ca62ecc..406d4859862004fb11847d4f77c380a7d4aca7ad 100644 (file)
@@ -25,13 +25,12 @@ shared-vram
 shadow-vram
 serial-non-block
 ioemu-save-restore
-ioemu-save-restore-ide
 ioemu-save-restore-usb
 ioemu-save-restore-timer
 ioemu-save-restore-rtl8139
 ioemu-save-restore-pcnet
 ioemu-save-restore-ne2000
-ide-hd-multithread
+#ide-hd-multithread
 acpi-support
 acpi-timer-support
 acpi-poweroff-support
@@ -51,7 +50,6 @@ xenstore-block-device-config
 xenstore-write-vnc-port
 domain-timeoffset
 qemu-allow-disable-sdl
-qemu-fix-memset-args
 xen-support-buffered-ioreqs
 ioemu-buffer-pio-ia64
 qemu-daemonize
@@ -62,22 +60,15 @@ qemu-pci
 qemu-pci-vendor-ids
 serial-port-rate-limit
 hypervisor-rtc
-ide-cd-dma
 vnc-password
 ne2000-bounds-checks
 xenstore-device-info-functions
 tpm-tis-device
 qemu-serial-fixes
-vnc-japan-keymap
 rtl8139-bound-chaining
 fix-interrupt-routing
-nodelay-serial-over-tcp
 remove-pci-bridge-setup
-limit-fdc-sector-size-to-16K
-usb-uhci-buffer-size
-vnc-monitor-shift-key-processing
 ide-error-reporting
-vnc-numpad-handling
 vnc-altgr-keysym
 xen-mapcache
 ioemu-save-restore-logdirty
index 76db48706aab113eda9aea1d7d76adb25bfeb8d3..e4420c3a6df24eb46612e3bd849e88ab92a91983 100644 (file)
@@ -1,8 +1,8 @@
 Index: ioemu/hw/vga.c
 ===================================================================
---- ioemu.orig/hw/vga.c        2007-05-02 10:32:35.000000000 +0100
-+++ ioemu/hw/vga.c     2007-05-02 10:35:05.000000000 +0100
-@@ -1359,6 +1359,105 @@
+--- ioemu.orig/hw/vga.c        2007-05-03 19:15:06.000000000 +0100
++++ ioemu/hw/vga.c     2007-05-03 19:15:57.000000000 +0100
+@@ -1373,6 +1373,105 @@
      }
  }
  
@@ -108,7 +108,7 @@ Index: ioemu/hw/vga.c
  /* 
   * graphic modes
   */
-@@ -1454,6 +1553,11 @@
+@@ -1468,6 +1567,11 @@
      printf("w=%d h=%d v=%d line_offset=%d cr[0x09]=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=0x%02x\n",
             width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
  #endif
@@ -120,7 +120,7 @@ Index: ioemu/hw/vga.c
      addr1 = (s->start_addr * 4);
      bwidth = width * 4;
      y_start = -1;
-@@ -1889,7 +1993,18 @@
+@@ -1918,7 +2022,18 @@
  
      vga_reset(s);
  
@@ -140,7 +140,7 @@ Index: ioemu/hw/vga.c
      s->vram_offset = vga_ram_offset;
      s->vram_size = vga_ram_size;
      s->ds = ds;
-@@ -2013,7 +2128,7 @@
+@@ -2058,7 +2173,7 @@
      }
  
      if (!vga_ram_base) {
@@ -149,7 +149,7 @@ Index: ioemu/hw/vga.c
          if (!vga_ram_base) {
              fprintf(stderr, "reallocate error\n");
              return NULL;
-@@ -2021,8 +2136,10 @@
+@@ -2066,8 +2181,10 @@
      }
  
      /* XXX lock needed? */
@@ -163,9 +163,9 @@ Index: ioemu/hw/vga.c
      return old_pointer;
 Index: ioemu/hw/vga_int.h
 ===================================================================
---- ioemu.orig/hw/vga_int.h    2007-05-02 10:32:35.000000000 +0100
-+++ ioemu/hw/vga_int.h 2007-05-02 10:35:10.000000000 +0100
-@@ -78,7 +78,9 @@
+--- ioemu.orig/hw/vga_int.h    2007-05-03 19:15:06.000000000 +0100
++++ ioemu/hw/vga_int.h 2007-05-03 19:15:57.000000000 +0100
+@@ -80,7 +80,9 @@
  #define VGA_MAX_HEIGHT 2048
  
  #define VGA_STATE_COMMON                                                \
index 5a1da4cddefa262792badd28de1719815180d898..0dba12d11cb228ffa1729b47bfba956b8ec4ad23 100644 (file)
@@ -1,7 +1,7 @@
 Index: ioemu/hw/cirrus_vga.c
 ===================================================================
---- ioemu.orig/hw/cirrus_vga.c 2007-05-03 09:56:32.000000000 +0100
-+++ ioemu/hw/cirrus_vga.c      2007-05-03 10:07:53.000000000 +0100
+--- ioemu.orig/hw/cirrus_vga.c 2007-05-03 18:18:00.000000000 +0100
++++ ioemu/hw/cirrus_vga.c      2007-05-03 19:15:06.000000000 +0100
 @@ -28,6 +28,9 @@
   */
  #include "vl.h"
@@ -39,7 +39,7 @@ Index: ioemu/hw/cirrus_vga.c
  /***************************************
   *
   *  prototypes.
-@@ -2520,6 +2529,83 @@
+@@ -2525,6 +2534,83 @@
      cirrus_linear_bitblt_writel,
  };
  
@@ -123,7 +123,7 @@ Index: ioemu/hw/cirrus_vga.c
  /* Compute the memory access functions */
  static void cirrus_update_memory_access(CirrusVGAState *s)
  {
-@@ -2538,11 +2624,37 @@
+@@ -2543,11 +2629,37 @@
          
        mode = s->gr[0x05] & 0x7;
        if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) {
@@ -161,7 +161,7 @@ Index: ioemu/hw/cirrus_vga.c
              s->cirrus_linear_write[0] = cirrus_linear_writeb;
              s->cirrus_linear_write[1] = cirrus_linear_writew;
              s->cirrus_linear_write[2] = cirrus_linear_writel;
-@@ -3136,6 +3248,13 @@
+@@ -3151,6 +3263,13 @@
      /* XXX: add byte swapping apertures */
      cpu_register_physical_memory(addr, s->vram_size,
                                 s->cirrus_linear_io_addr);
@@ -177,31 +177,36 @@ Index: ioemu/hw/cirrus_vga.c
  }
 Index: ioemu/hw/pc.c
 ===================================================================
---- ioemu.orig/hw/pc.c 2007-05-03 10:07:53.000000000 +0100
-+++ ioemu/hw/pc.c      2007-05-03 10:07:53.000000000 +0100
-@@ -790,14 +790,14 @@
+--- ioemu.orig/hw/pc.c 2007-05-03 19:15:05.000000000 +0100
++++ ioemu/hw/pc.c      2007-05-03 19:15:51.000000000 +0100
+@@ -639,18 +639,18 @@
      if (cirrus_vga_enabled) {
          if (pci_enabled) {
              pci_cirrus_vga_init(pci_bus, 
 -                                ds, phys_ram_base + ram_size, ram_size, 
-+                                ds, NULL, ram_size,
++                                ds, NULL, ram_size, 
                                  vga_ram_size);
          } else {
 -            isa_cirrus_vga_init(ds, phys_ram_base + ram_size, ram_size, 
-+            isa_cirrus_vga_init(ds, NULL, ram_size,
++            isa_cirrus_vga_init(ds, NULL, ram_size, 
                                  vga_ram_size);
          }
      } else {
--        vga_initialize(pci_bus, ds, phys_ram_base + ram_size, ram_size, 
-+        vga_initialize(pci_bus, ds, NULL, ram_size,
-                        vga_ram_size, 0, 0);
+         if (pci_enabled) {
+-            pci_vga_init(pci_bus, ds, phys_ram_base + ram_size, ram_size, 
++            pci_vga_init(pci_bus, ds, NULL, ram_size, 
+                          vga_ram_size, 0, 0);
+         } else {
+-            isa_vga_init(ds, phys_ram_base + ram_size, ram_size, 
++            isa_vga_init(ds, NULL, ram_size, 
+                          vga_ram_size);
+         }
      }
 Index: ioemu/hw/vga.c
 ===================================================================
---- ioemu.orig/hw/vga.c        2007-05-03 10:07:52.000000000 +0100
-+++ ioemu/hw/vga.c     2007-05-03 10:07:53.000000000 +0100
-@@ -1858,6 +1858,7 @@
+--- ioemu.orig/hw/vga.c        2007-05-03 19:11:39.000000000 +0100
++++ ioemu/hw/vga.c     2007-05-03 19:15:06.000000000 +0100
+@@ -1887,6 +1887,7 @@
      /* TODO: add vbe support if enabled */
  }
  
@@ -209,7 +214,7 @@ Index: ioemu/hw/vga.c
  void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base, 
                       unsigned long vga_ram_offset, int vga_ram_size)
  {
-@@ -1888,7 +1889,7 @@
+@@ -1917,7 +1918,7 @@
  
      vga_reset(s);
  
@@ -218,7 +223,7 @@ Index: ioemu/hw/vga.c
      s->vram_offset = vga_ram_offset;
      s->vram_size = vga_ram_size;
      s->ds = ds;
-@@ -2002,6 +2003,31 @@
+@@ -2047,6 +2048,31 @@
      return 0;
  }
  
@@ -252,9 +257,9 @@ Index: ioemu/hw/vga.c
  
 Index: ioemu/hw/vga_int.h
 ===================================================================
---- ioemu.orig/hw/vga_int.h    2007-05-03 09:56:32.000000000 +0100
-+++ ioemu/hw/vga_int.h 2007-05-03 10:07:53.000000000 +0100
-@@ -169,5 +169,6 @@
+--- ioemu.orig/hw/vga_int.h    2007-05-03 18:38:09.000000000 +0100
++++ ioemu/hw/vga_int.h 2007-05-03 19:15:06.000000000 +0100
+@@ -174,5 +174,6 @@
                               unsigned int color0, unsigned int color1,
                               unsigned int color_xor);
  
@@ -263,9 +268,9 @@ Index: ioemu/hw/vga_int.h
  extern const uint8_t gr_mask[16];
 Index: ioemu/vl.c
 ===================================================================
---- ioemu.orig/vl.c    2007-05-03 10:07:53.000000000 +0100
-+++ ioemu/vl.c 2007-05-03 10:07:53.000000000 +0100
-@@ -5745,6 +5745,62 @@
+--- ioemu.orig/vl.c    2007-05-03 19:15:05.000000000 +0100
++++ ioemu/vl.c 2007-05-03 19:15:06.000000000 +0100
+@@ -6660,6 +6660,62 @@
  
  #define MAX_NET_CLIENTS 32
  
@@ -330,9 +335,9 @@ Index: ioemu/vl.c
  #ifdef CONFIG_GDBSTUB
 Index: ioemu/vl.h
 ===================================================================
---- ioemu.orig/vl.h    2007-05-03 10:07:53.000000000 +0100
-+++ ioemu/vl.h 2007-05-03 10:07:53.000000000 +0100
-@@ -145,6 +145,13 @@
+--- ioemu.orig/vl.h    2007-05-03 19:12:02.000000000 +0100
++++ ioemu/vl.h 2007-05-03 19:15:06.000000000 +0100
+@@ -150,6 +150,13 @@
  
  void main_loop_wait(int timeout);
  
index 9b5e4728b17d4fbad73f88016e012a93b17d4b4b..82f0b21fcbd5cad6fe41f05d7a13ed242b67af56 100644 (file)
@@ -1,8 +1,8 @@
 Index: ioemu/vl.c
 ===================================================================
---- ioemu.orig/vl.c    2007-05-03 10:24:03.000000000 +0100
-+++ ioemu/vl.c 2007-05-03 10:24:04.000000000 +0100
-@@ -1537,26 +1537,108 @@
+--- ioemu.orig/vl.c    2007-05-03 19:12:00.000000000 +0100
++++ ioemu/vl.c 2007-05-03 19:14:57.000000000 +0100
+@@ -1671,26 +1671,108 @@
      return chr;
  }
  
@@ -92,7 +92,7 @@ Index: ioemu/vl.c
 +}
 +
  #if defined(__linux__)
- CharDriverState *qemu_chr_open_pty(void)
static CharDriverState *qemu_chr_open_pty(void)
  {
      struct termios tty;
 -    char slave_name[1024];
@@ -120,7 +120,7 @@ Index: ioemu/vl.c
      return qemu_chr_open_fd(master_fd, master_fd);
  }
  
-@@ -5881,7 +5963,9 @@
+@@ -6799,7 +6881,9 @@
                  break;
              case QEMU_OPTION_nographic:
                  pstrcpy(monitor_device, sizeof(monitor_device), "stdio");
@@ -131,7 +131,7 @@ Index: ioemu/vl.c
                  nographic = 1;
                  break;
              case QEMU_OPTION_kernel:
-@@ -6348,16 +6432,23 @@
+@@ -7365,17 +7449,24 @@
          fprintf(stderr, "qemu: could not open monitor device '%s'\n", monitor_device);
          exit(1);
      }
@@ -139,12 +139,13 @@ Index: ioemu/vl.c
      monitor_init(monitor_hd, !nographic);
  
      for(i = 0; i < MAX_SERIAL_PORTS; i++) {
-         if (serial_devices[i][0] != '\0') {
+         const char *devname = serial_devices[i];
+         if (devname[0] != '\0' && strcmp(devname, "none")) {
 +            char buf[16];
-             serial_hds[i] = qemu_chr_open(serial_devices[i]);
+             serial_hds[i] = qemu_chr_open(devname);
              if (!serial_hds[i]) {
                  fprintf(stderr, "qemu: could not open serial device '%s'\n", 
-                         serial_devices[i]);
+                         devname);
                  exit(1);
              }
 +            snprintf(buf, sizeof(buf), "/serial/%d", i);
@@ -152,22 +153,22 @@ Index: ioemu/vl.c
 +            if (i == 0) /* serial 0 is also called the console */
 +                store_dev_info(serial_devices[i], domid,
 +                               serial_hds[i], "/console");
-             if (!strcmp(serial_devices[i], "vc"))
+             if (!strcmp(devname, "vc"))
                  qemu_chr_printf(serial_hds[i], "serial%d console\r\n", i);
          }
-@@ -6365,12 +6456,15 @@
+@@ -7384,12 +7475,15 @@
      for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
-         if (parallel_devices[i][0] != '\0') {
+         const char *devname = parallel_devices[i];
+         if (devname[0] != '\0' && strcmp(devname, "none")) {
 +            char buf[16];
-             parallel_hds[i] = qemu_chr_open(parallel_devices[i]);
+             parallel_hds[i] = qemu_chr_open(devname);
              if (!parallel_hds[i]) {
                  fprintf(stderr, "qemu: could not open parallel device '%s'\n", 
-                         parallel_devices[i]);
+                         devname);
                  exit(1);
              }
 +            snprintf(buf, sizeof(buf), "/parallel/%d", i);
 +            store_dev_info(parallel_devices[i], domid, parallel_hds[i], buf);
-             if (!strcmp(parallel_devices[i], "vc"))
+             if (!strcmp(devname, "vc"))
                  qemu_chr_printf(parallel_hds[i], "parallel%d console\r\n", i);
          }
index 909d23b42000bb883ee813a29f7c32c714f6a55e..e4180d40b681ff113596b9632256711df8450e9a 100644 (file)
@@ -22,21 +22,21 @@ Signed-off-by: Stefan Berger <stefanb@us.ibm.com>
 
 Index: ioemu/Makefile.target
 ===================================================================
---- ioemu.orig/Makefile.target 2007-05-03 15:20:44.000000000 +0100
-+++ ioemu/Makefile.target      2007-05-03 15:20:44.000000000 +0100
-@@ -369,6 +369,7 @@
+--- ioemu.orig/Makefile.target 2007-05-03 20:38:49.000000000 +0100
++++ ioemu/Makefile.target      2007-05-03 20:39:04.000000000 +0100
+@@ -400,6 +400,7 @@
  VL_OBJS+= piix4acpi.o
  VL_OBJS+= xenstore.o
  VL_OBJS+= xen_platform.o
 +VL_OBJS+= tpm_tis.o
DEFINES += -DHAS_AUDIO
CPPFLAGS += -DHAS_AUDIO
  endif
  ifeq ($(TARGET_BASE_ARCH), ppc)
 Index: ioemu/hw/pc.c
 ===================================================================
---- ioemu.orig/hw/pc.c 2007-05-03 15:20:43.000000000 +0100
-+++ ioemu/hw/pc.c      2007-05-03 15:20:44.000000000 +0100
-@@ -877,6 +877,9 @@
+--- ioemu.orig/hw/pc.c 2007-05-03 20:32:20.000000000 +0100
++++ ioemu/hw/pc.c      2007-05-03 20:38:55.000000000 +0100
+@@ -730,6 +730,9 @@
          }
      }
  
@@ -49,7 +49,7 @@ Index: ioemu/hw/pc.c
 Index: ioemu/hw/tpm_tis.c
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ ioemu/hw/tpm_tis.c 2007-05-03 15:20:44.000000000 +0100
++++ ioemu/hw/tpm_tis.c 2007-05-03 20:38:55.000000000 +0100
 @@ -0,0 +1,1128 @@
 +/*
 + * tpm_tis.c - QEMU emulator for a 1.2 TPM with TIS interface
@@ -1181,11 +1181,11 @@ Index: ioemu/hw/tpm_tis.c
 +}
 Index: ioemu/vl.h
 ===================================================================
---- ioemu.orig/vl.h    2007-05-03 15:20:44.000000000 +0100
-+++ ioemu/vl.h 2007-05-03 15:20:44.000000000 +0100
-@@ -933,6 +933,10 @@
- void piix4_pm_init(PCIBus *bus, int devfn);
void acpi_bios_init(void);
+--- ioemu.orig/vl.h    2007-05-03 20:38:53.000000000 +0100
++++ ioemu/vl.h 2007-05-03 20:38:55.000000000 +0100
+@@ -1088,6 +1088,10 @@
+ /* smbus_eeprom.c */
SMBusDevice *smbus_eeprom_device_init(uint8_t addr, uint8_t *buf);
  
 +/* tpm_tis.c */
 +int has_tpm_device(void);
index 5ce541ce95ad86fce948d53d9ff2724ad5ac0983..d5e9b28ccf38a25b60c25ea8b5398456d92e40ea 100644 (file)
@@ -18,17 +18,17 @@ Signed-off-by: Xinmei Huang <xinmei.huang@intel.com>
 
 Index: ioemu/hw/usb-hid.c
 ===================================================================
---- ioemu.orig/hw/usb-hid.c    2007-05-02 14:21:51.000000000 +0100
-+++ ioemu/hw/usb-hid.c 2007-05-02 14:23:54.000000000 +0100
+--- ioemu.orig/hw/usb-hid.c    2007-05-09 14:11:27.000000000 +0100
++++ ioemu/hw/usb-hid.c 2007-05-09 14:12:06.000000000 +0100
 @@ -39,6 +39,7 @@
      int x, y;
      int kind;
      int mouse_grabbed;
 +    int status_changed;
+     QEMUPutMouseEntry *eh_entry;
  } USBMouseState;
  
- /* mostly the same values as the Bochs USB Mouse device */
-@@ -231,6 +232,7 @@
+@@ -232,6 +233,7 @@
      s->dy += dy1;
      s->dz += dz1;
      s->buttons_state = buttons_state;
@@ -36,7 +36,7 @@ Index: ioemu/hw/usb-hid.c
  }
  
  static void usb_tablet_event(void *opaque,
-@@ -242,6 +244,7 @@
+@@ -243,6 +245,7 @@
      s->y = y;
      s->dz += dz;
      s->buttons_state = buttons_state;
@@ -44,18 +44,18 @@ Index: ioemu/hw/usb-hid.c
  }
  
  static inline int int_clamp(int val, int vmin, int vmax)
-@@ -483,10 +486,16 @@
-     switch(pid) {
+@@ -485,10 +488,16 @@
+     switch(p->pid) {
      case USB_TOKEN_IN:
-         if (devep == 1) {
+         if (p->devep == 1) {
 -          if (s->kind == USB_MOUSE)
--              ret = usb_mouse_poll(s, data, len);
+-              ret = usb_mouse_poll(s, p->data, p->len);
 -          else if (s->kind == USB_TABLET)
--              ret = usb_tablet_poll(s, data, len);
+-              ret = usb_tablet_poll(s, p->data, p->len);
 +            if (s->kind == USB_MOUSE)
-+                ret = usb_mouse_poll(s, data, len);
++                ret = usb_mouse_poll(s, p->data, p->len);
 +            else if (s->kind == USB_TABLET)
-+                ret = usb_tablet_poll(s, data, len);
++                ret = usb_tablet_poll(s, p->data, p->len);
 +
 +            if (!s->status_changed)
 +                ret = USB_RET_NAK;
@@ -65,7 +65,7 @@ Index: ioemu/hw/usb-hid.c
          } else {
              goto fail;
          }
-@@ -566,6 +575,7 @@
+@@ -570,6 +579,7 @@
      s->dev.handle_data = usb_mouse_handle_data;
      s->dev.handle_destroy = usb_mouse_handle_destroy;
      s->kind = USB_TABLET;
@@ -73,7 +73,7 @@ Index: ioemu/hw/usb-hid.c
  
      pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Tablet");
  
-@@ -589,6 +599,7 @@
+@@ -593,6 +603,7 @@
      s->dev.handle_data = usb_mouse_handle_data;
      s->dev.handle_destroy = usb_mouse_handle_destroy;
      s->kind = USB_MOUSE;
@@ -83,8 +83,8 @@ Index: ioemu/hw/usb-hid.c
  
 Index: ioemu/hw/usb-uhci.c
 ===================================================================
---- ioemu.orig/hw/usb-uhci.c   2007-05-02 14:23:54.000000000 +0100
-+++ ioemu/hw/usb-uhci.c        2007-05-02 14:23:54.000000000 +0100
+--- ioemu.orig/hw/usb-uhci.c   2007-05-09 14:12:05.000000000 +0100
++++ ioemu/hw/usb-uhci.c        2007-05-09 14:12:06.000000000 +0100
 @@ -43,9 +43,15 @@
  #define TD_CTRL_IOC     (1 << 24)
  #define TD_CTRL_ACTIVE  (1 << 23)
@@ -101,35 +101,43 @@ Index: ioemu/hw/usb-uhci.c
  
  #define UHCI_PORT_RESET (1 << 9)
  #define UHCI_PORT_LSDA  (1 << 8)
-@@ -424,12 +430,12 @@
-     uint8_t buf[2048];
+@@ -431,13 +437,13 @@
+     uint8_t pid;
      int len, max_len, err, ret;
  
+-    /* ??? This is wrong for async completion.  */
 -    if (td->ctrl & TD_CTRL_IOC) {
 -        *int_mask |= 0x01;
-+    if (!(td->ctrl & TD_CTRL_ACTIVE)){
++    if (!(td->ctrl & TD_CTRL_ACTIVE)) {
 +        ret = 1;
-+        goto out;
++      goto out;
      }
 -    
 -    if (!(td->ctrl & TD_CTRL_ACTIVE))
 -        return 1;
++
 +    /* Clear TD's status field explicitly */
 +    td->ctrl = td->ctrl & (~TD_CTRL_MASK);
  
      /* TD is active */
      max_len = ((td->token >> 21) + 1) & 0x7ff;
-@@ -467,7 +473,8 @@
-         /* invalid pid : frame interrupted */
-         s->status |= UHCI_STS_HCPERR;
-         uhci_update_irq(s);
--        return -1;
-+        ret = -1;
-+        goto out;
+@@ -493,11 +499,13 @@
+             /* invalid pid : frame interrupted */
+             s->status |= UHCI_STS_HCPERR;
+             uhci_update_irq(s);
+-            return -1;
++            ret = -1;
++          goto out;
+         }
+     }
+     if (ret == USB_RET_ASYNC) {
+-        return 2;
++        ret = 2;
++      goto out;
      }
      if (td->ctrl & TD_CTRL_IOS)
          td->ctrl &= ~TD_CTRL_ACTIVE;
-@@ -479,10 +486,12 @@
+@@ -509,10 +517,12 @@
              len < max_len) {
              *int_mask |= 0x02;
              /* short packet: do not update QH */
@@ -144,7 +152,7 @@ Index: ioemu/hw/usb-uhci.c
          }
      } else {
          switch(ret) {
-@@ -501,23 +510,34 @@
+@@ -531,23 +541,34 @@
              }
              td->ctrl = (td->ctrl & ~(3 << TD_CTRL_ERROR_SHIFT)) | 
                  (err << TD_CTRL_ERROR_SHIFT);
@@ -182,4 +190,4 @@ Index: ioemu/hw/usb-uhci.c
 +    return ret;
  }
  
- static void uhci_frame_timer(void *opaque)
+ static void uhci_async_complete_packet(USBPacket * packet, void *opaque)
index 4607815ea8f766a026823ad05536ae3283ce7016..f7a73bf4b4da65ac30243e0f0255f8875b9ea764 100644 (file)
@@ -1,7 +1,7 @@
 Index: ioemu/vnc.c
 ===================================================================
---- ioemu.orig/vnc.c   2006-12-06 23:46:11.000000000 +0000
-+++ ioemu/vnc.c        2006-12-06 23:46:11.000000000 +0000
+--- ioemu.orig/vnc.c   2007-05-03 19:50:17.000000000 +0100
++++ ioemu/vnc.c        2007-05-03 19:54:29.000000000 +0100
 @@ -33,6 +33,10 @@
  #include "vnc_keysym.h"
  #include "keymaps.c"
@@ -13,101 +13,3 @@ Index: ioemu/vnc.c
  typedef struct Buffer
  {
      size_t capacity;
-@@ -96,6 +100,8 @@
-     int visible_h;
-     int slow_client;
-+
-+    int ctl_keys;               /* Ctrl+Alt starts calibration */
- };
- #define DIRTY_PIXEL_BITS 64
-@@ -796,16 +802,80 @@
- static void do_key_event(VncState *vs, int down, uint32_t sym)
- {
--    int keycode;
-+    sym &= 0xFFFF;
--    keycode = keysym2scancode(vs->kbd_layout, sym & 0xFFFF);
-+    if (is_graphic_console()) {
-+      int keycode;
--    if (keycode & 0x80)
--      kbd_put_keycode(0xe0);
--    if (down)
--      kbd_put_keycode(keycode & 0x7f);
--    else
--      kbd_put_keycode(keycode | 0x80);
-+      keycode = keysym2scancode(vs->kbd_layout, sym);
-+      if (keycode & 0x80)
-+          kbd_put_keycode(0xe0);
-+      if (down)
-+          kbd_put_keycode(keycode & 0x7f);
-+      else
-+          kbd_put_keycode(keycode | 0x80);
-+    } else if (down) {
-+      int qemu_keysym = 0;
-+
-+      if (sym <= 128) /* normal ascii */
-+          qemu_keysym = sym;
-+      else {
-+          switch (sym) {
-+          case XK_Up: qemu_keysym = QEMU_KEY_UP; break;
-+          case XK_Down: qemu_keysym = QEMU_KEY_DOWN; break;
-+          case XK_Left: qemu_keysym = QEMU_KEY_LEFT; break;
-+          case XK_Right: qemu_keysym = QEMU_KEY_RIGHT; break;
-+          case XK_Home: qemu_keysym = QEMU_KEY_HOME; break;
-+          case XK_End: qemu_keysym = QEMU_KEY_END; break;
-+          case XK_Page_Up: qemu_keysym = QEMU_KEY_PAGEUP; break;
-+          case XK_Page_Down: qemu_keysym = QEMU_KEY_PAGEDOWN; break;
-+          case XK_BackSpace: qemu_keysym = QEMU_KEY_BACKSPACE; break;
-+          case XK_Delete: qemu_keysym = QEMU_KEY_DELETE; break;
-+          case XK_Return:
-+          case XK_Linefeed: qemu_keysym = sym; break;
-+          default: break;
-+          }
-+      }
-+      if (qemu_keysym != 0)
-+          kbd_put_keysym(qemu_keysym);
-+    }
-+
-+    if (down) {
-+      switch (sym) {
-+      case XK_Control_L:
-+          vs->ctl_keys |= 1;
-+          break;
-+
-+      case XK_Alt_L:
-+          vs->ctl_keys |= 2;
-+          break;
-+
-+      default:
-+          break;
-+      }
-+    } else {
-+      switch (sym) {
-+      case XK_Control_L:
-+          vs->ctl_keys &= ~1;
-+          break;
-+
-+      case XK_Alt_L:
-+          vs->ctl_keys &= ~2;
-+          break;
-+
-+      case XK_1 ... XK_9:
-+          if ((vs->ctl_keys & 3) != 3)
-+              break;
-+
-+          console_select(sym - XK_1);
-+          if (is_graphic_console()) {
-+              /* tell the vga console to redisplay itself */
-+              vga_hw_invalidate();
-+              vnc_dpy_update(vs->ds, 0, 0, vs->ds->width, vs->ds->height);
-+          }
-+          break;
-+      }
-+    }
- }
- static void key_event(VncState *vs, int down, uint32_t sym)
index 1d12ab6edea90ce74d2bafa8713fa199f117a03b..81a7113f695f475407eb916701f6150b3a1caf65 100644 (file)
@@ -1,7 +1,7 @@
 Index: ioemu/vnc.c
 ===================================================================
---- ioemu.orig/vnc.c   2007-05-03 10:07:56.000000000 +0100
-+++ ioemu/vnc.c        2007-05-03 10:07:56.000000000 +0100
+--- ioemu.orig/vnc.c   2007-05-03 20:22:19.000000000 +0100
++++ ioemu/vnc.c        2007-05-03 20:23:38.000000000 +0100
 @@ -28,7 +28,19 @@
  #include "qemu_socket.h"
  #include <assert.h>
@@ -36,16 +36,16 @@ Index: ioemu/vnc.c
      int width;
      int height;
      uint64_t *dirty_row;      /* screen regions which are possibly dirty */
-@@ -99,8 +112,6 @@
+@@ -106,8 +119,6 @@
      int visible_w;
      int visible_h;
  
 -    int slow_client;
 -
-     int ctl_keys;               /* Ctrl+Alt starts calibration */
+     /* input */
+     uint8_t modifiers_state[256];
  };
-@@ -383,7 +394,7 @@
+@@ -412,7 +423,7 @@
      int y = 0;
      int pitch = ds->linesize;
      VncState *vs = ds->opaque;
@@ -54,7 +54,7 @@ Index: ioemu/vnc.c
  
      if (src_x < vs->visible_x || src_y < vs->visible_y ||
        dst_x < vs->visible_x || dst_y < vs->visible_y ||
-@@ -393,10 +404,8 @@
+@@ -422,10 +433,8 @@
        (dst_y + h) > (vs->visible_y + vs->visible_h))
        updating_client = 0;
  
@@ -66,7 +66,7 @@ Index: ioemu/vnc.c
  
      if (dst_y > src_y) {
        y = h - 1;
-@@ -448,110 +457,149 @@
+@@ -477,110 +486,149 @@
  static void _vnc_update_client(void *opaque)
  {
      VncState *vs = opaque;
@@ -299,7 +299,7 @@ Index: ioemu/vnc.c
  }
  
  static void vnc_update_client(void *opaque)
-@@ -564,8 +612,10 @@
+@@ -593,8 +641,10 @@
  
  static void vnc_timer_init(VncState *vs)
  {
@@ -311,7 +311,7 @@ Index: ioemu/vnc.c
  }
  
  static void vnc_dpy_refresh(DisplayState *ds)
-@@ -625,7 +675,6 @@
+@@ -654,7 +704,6 @@
        vs->csock = -1;
        buffer_reset(&vs->input);
        buffer_reset(&vs->output);
@@ -319,7 +319,7 @@ Index: ioemu/vnc.c
        return 0;
      }
      return ret;
-@@ -897,7 +946,6 @@
+@@ -961,7 +1010,6 @@
                                       int x_position, int y_position,
                                       int w, int h)
  {
@@ -327,7 +327,7 @@ Index: ioemu/vnc.c
      if (!incremental)
        framebuffer_set_updated(vs, x_position, y_position, w, h);
      vs->visible_x = x_position;
-@@ -1020,6 +1068,7 @@
+@@ -1091,6 +1139,7 @@
  {
      int i;
      uint16_t limit;
@@ -335,7 +335,7 @@ Index: ioemu/vnc.c
  
      switch (data[0]) {
      case 0:
-@@ -1063,12 +1112,18 @@
+@@ -1134,12 +1183,18 @@
        if (len == 1)
            return 8;
  
@@ -356,9 +356,9 @@ Index: ioemu/vnc.c
      case 6:
 Index: ioemu/vl.c
 ===================================================================
---- ioemu.orig/vl.c    2007-05-03 10:07:56.000000000 +0100
-+++ ioemu/vl.c 2007-05-03 10:07:56.000000000 +0100
-@@ -725,6 +725,12 @@
+--- ioemu.orig/vl.c    2007-05-03 20:23:03.000000000 +0100
++++ ioemu/vl.c 2007-05-03 20:23:30.000000000 +0100
+@@ -812,6 +812,12 @@
      }
  }
  
@@ -373,9 +373,9 @@ Index: ioemu/vl.c
  void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time)
 Index: ioemu/vl.h
 ===================================================================
---- ioemu.orig/vl.h    2007-05-03 10:07:56.000000000 +0100
-+++ ioemu/vl.h 2007-05-03 10:07:56.000000000 +0100
-@@ -407,6 +407,7 @@
+--- ioemu.orig/vl.h    2007-05-03 20:23:25.000000000 +0100
++++ ioemu/vl.h 2007-05-03 20:23:30.000000000 +0100
+@@ -443,6 +443,7 @@
  void qemu_free_timer(QEMUTimer *ts);
  void qemu_del_timer(QEMUTimer *ts);
  void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time);
index 12efe7ce93c5660881740c58291931bb6af7c14e..db44e06f63590cfa4cd1c6c0556e86ddab884fad 100644 (file)
@@ -1,8 +1,8 @@
 Index: ioemu/vnc.c
 ===================================================================
---- ioemu.orig/vnc.c   2007-05-03 09:56:31.000000000 +0100
-+++ ioemu/vnc.c        2007-05-03 10:07:55.000000000 +0100
-@@ -143,13 +143,16 @@
+--- ioemu.orig/vnc.c   2007-05-03 18:17:59.000000000 +0100
++++ ioemu/vnc.c        2007-05-03 19:46:19.000000000 +0100
+@@ -170,13 +170,16 @@
  static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h)
  {
      VncState *vs = ds->opaque;
@@ -22,7 +22,7 @@ Index: ioemu/vnc.c
  }
  
  static void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
-@@ -373,6 +376,7 @@
+@@ -402,6 +405,7 @@
  static void vnc_update_client(void *opaque)
  {
      VncState *vs = opaque;
@@ -30,7 +30,7 @@ Index: ioemu/vnc.c
  
      if (vs->need_update && vs->csock != -1) {
        int y;
-@@ -383,6 +387,8 @@
+@@ -412,6 +416,8 @@
        int saved_offset;
        int has_dirty = 0;
  
@@ -39,7 +39,7 @@ Index: ioemu/vnc.c
          vnc_set_bits(width_mask, (vs->width / 16), VNC_DIRTY_WORDS);
  
        /* Walk through the dirty map and eliminate tiles that
-@@ -390,7 +396,7 @@
+@@ -419,7 +425,7 @@
        row = vs->ds->data;
        old_row = vs->old_data;
  
@@ -48,7 +48,7 @@ Index: ioemu/vnc.c
            if (vnc_and_bits(vs->dirty_row[y], width_mask, VNC_DIRTY_WORDS)) {
                int x;
                char *ptr, *old_ptr;
-@@ -415,10 +421,8 @@
+@@ -444,10 +450,8 @@
            old_row += vs->ds->linesize;
        }
  
@@ -60,7 +60,7 @@ Index: ioemu/vnc.c
  
        /* Count rectangles */
        n_rectangles = 0;
-@@ -454,17 +458,13 @@
+@@ -483,17 +487,13 @@
        vs->output.buffer[saved_offset] = (n_rectangles >> 8) & 0xFF;
        vs->output.buffer[saved_offset + 1] = n_rectangles & 0xFF;
        vnc_flush(vs);
@@ -79,7 +79,7 @@ Index: ioemu/vnc.c
  }
  
  static void vnc_dpy_refresh(DisplayState *ds)
-@@ -736,6 +736,8 @@
+@@ -864,6 +864,8 @@
            old_row += vs->ds->linesize;
        }
      }
@@ -90,9 +90,9 @@ Index: ioemu/vnc.c
  static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
 Index: ioemu/vl.c
 ===================================================================
---- ioemu.orig/vl.c    2007-05-03 10:07:54.000000000 +0100
-+++ ioemu/vl.c 2007-05-03 10:07:55.000000000 +0100
-@@ -5195,10 +5195,10 @@
+--- ioemu.orig/vl.c    2007-05-03 19:44:49.000000000 +0100
++++ ioemu/vl.c 2007-05-03 19:46:19.000000000 +0100
+@@ -6085,10 +6085,10 @@
          /* XXX: better handling of removal */
          for(ioh = first_io_handler; ioh != NULL; ioh = ioh_next) {
              ioh_next = ioh->next;
index f5d3a73bf1deefacda1d9838da7936010fa21b42..fe324d356f5ff2504d774a7259abff6246d6778f 100644 (file)
@@ -1,58 +1,53 @@
 Index: ioemu/vnc.c
 ===================================================================
---- ioemu.orig/vnc.c   2007-05-03 10:24:06.000000000 +0100
-+++ ioemu/vnc.c        2007-05-03 10:24:06.000000000 +0100
-@@ -1197,7 +1197,7 @@
-     }
- }
+--- ioemu.orig/vnc.c   2007-05-09 14:12:04.000000000 +0100
++++ ioemu/vnc.c        2007-05-09 14:12:21.000000000 +0100
+@@ -1270,7 +1270,7 @@
+ extern int parse_host_port(struct sockaddr_in *saddr, const char *str);
  
--void vnc_display_init(DisplayState *ds, int display)
-+int vnc_display_init(DisplayState *ds, int display, int find_unused)
+-void vnc_display_init(DisplayState *ds, const char *arg)
++int vnc_display_init(DisplayState *ds, const char *arg, int find_unused)
  {
-     struct sockaddr_in addr;
-     int reuse_addr, ret;
-@@ -1228,10 +1228,6 @@
-       exit(1);
-     }
+     struct sockaddr *addr;
+     struct sockaddr_in iaddr;
+@@ -1312,6 +1312,9 @@
  
--    addr.sin_family = AF_INET;
--    addr.sin_port = htons(5900 + display);
--    memset(&addr.sin_addr, 0, sizeof(addr.sin_addr));
--
-     reuse_addr = 1;
-     ret = setsockopt(vs->lsock, SOL_SOCKET, SO_REUSEADDR,
-                    (const char *)&reuse_addr, sizeof(reuse_addr));
-@@ -1240,7 +1236,16 @@
-       exit(1);
+     vnc_dpy_resize(vs->ds, 640, 400);
++    if (arg == NULL)
++      arg = "localhost:0";
++    
+ #ifndef _WIN32
+     if (strstart(arg, "unix:", &p)) {
+       addr = (struct sockaddr *)&uaddr;
+@@ -1356,7 +1359,11 @@
+       }
      }
  
-+ retry:
-+    addr.sin_family = AF_INET;
-+    addr.sin_port = htons(5900 + display);
-+    memset(&addr.sin_addr, 0, sizeof(addr.sin_addr));
-+
-     if (bind(vs->lsock, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
+-    if (bind(vs->lsock, addr, addrlen) == -1) {
++    while (bind(vs->lsock, addr, addrlen) == -1) {
 +      if (find_unused && errno == EADDRINUSE) {
-+          display++;
-+          goto retry;
++          iaddr.sin_port = htons(ntohs(iaddr.sin_port) + 1);
++          continue;
 +      }
        fprintf(stderr, "bind() failed\n");
        exit(1);
      }
-@@ -1261,6 +1266,8 @@
-     vs->ds->dpy_refresh = vnc_dpy_refresh;
-     vnc_dpy_resize(vs->ds, 640, 400);
+@@ -1370,6 +1377,8 @@
+     if (ret == -1) {
+       exit(1);
+     }
 +
-+    return display;
++    return ntohs(iaddr.sin_port);
  }
  
  int vnc_start_viewer(int port)
 Index: ioemu/vl.c
 ===================================================================
---- ioemu.orig/vl.c    2007-05-03 10:24:06.000000000 +0100
-+++ ioemu/vl.c 2007-05-03 10:24:06.000000000 +0100
-@@ -122,6 +122,7 @@
+--- ioemu.orig/vl.c    2007-05-09 14:12:03.000000000 +0100
++++ ioemu/vl.c 2007-05-09 14:12:16.000000000 +0100
+@@ -132,6 +132,7 @@
  static DisplayState display_state;
  int nographic;
  int vncviewer;
@@ -60,15 +55,15 @@ Index: ioemu/vl.c
  const char* keyboard_layout = NULL;
  int64_t ticks_per_sec;
  int boot_device = 'c';
-@@ -5417,6 +5418,7 @@
+@@ -6311,6 +6312,7 @@
             "-loadvm file    start right away with a saved state (loadvm in monitor)\n"
           "-vnc display    start a VNC server on display\n"
             "-vncviewer      start a vncviewer process for this domain\n"
 +           "-vncunused      bind the VNC server to an unused port\n"
-            "-acpi           disable or enable ACPI of HVM domain \n"
-            "\n"
-            "During emulation, the following keys are useful:\n"
-@@ -5504,6 +5506,7 @@
+ #ifndef _WIN32
+          "-daemonize      daemonize QEMU after initializing\n"
+ #endif
+@@ -6407,6 +6409,7 @@
      QEMU_OPTION_vcpus,
      QEMU_OPTION_acpi,
      QEMU_OPTION_vncviewer,
@@ -76,15 +71,15 @@ Index: ioemu/vl.c
  };
  
  typedef struct QEMUOption {
-@@ -5579,6 +5582,7 @@
+@@ -6486,6 +6489,7 @@
      { "smp", HAS_ARG, QEMU_OPTION_smp },
      { "vnc", HAS_ARG, QEMU_OPTION_vnc },
      { "vncviewer", 0, QEMU_OPTION_vncviewer },
 +    { "vncunused", 0, QEMU_OPTION_vncunused },
-     
      /* temporary options */
      { "usb", 0, QEMU_OPTION_usb },
-@@ -5938,6 +5942,7 @@
+@@ -6853,6 +6857,7 @@
      snapshot = 0;
      nographic = 0;
      vncviewer = 0;
@@ -92,37 +87,57 @@ Index: ioemu/vl.c
      kernel_filename = NULL;
      kernel_cmdline = "";
  #ifdef TARGET_PPC
-@@ -6336,6 +6341,11 @@
+@@ -7272,12 +7277,15 @@
              case QEMU_OPTION_vncviewer:
                  vncviewer++;
                  break;
 +            case QEMU_OPTION_vncunused:
 +                vncunused++;
-+                if (vnc_display == -1)
-+                    vnc_display = 0;
 +                break;
              }
          }
      }
-@@ -6537,7 +6547,7 @@
+ #ifndef _WIN32
+-    if (daemonize && !nographic && vnc_display == NULL) {
++    if (daemonize && !nographic && vnc_display == NULL && vncunused == 0) {
+       fprintf(stderr, "Can only daemonize if using -nographic or -vnc\n");
+       daemonize = 0;
+     }
+@@ -7553,10 +7561,11 @@
+     /* terminal init */
      if (nographic) {
          dumb_display_init(ds);
-     } else if (vnc_display != -1) {
+-    } else if (vnc_display != NULL) {
 -      vnc_display_init(ds, vnc_display);
-+      vnc_display = vnc_display_init(ds, vnc_display, vncunused);
++    } else if (vnc_display != NULL || vncunused != 0) {
++      int vnc_display_port;
++      vnc_display_port = vnc_display_init(ds, vnc_display, vncunused);
        if (vncviewer)
-           vnc_start_viewer(vnc_display);
+-          vnc_start_viewer(vnc_display);
++          vnc_start_viewer(vnc_display_port);
      } else {
+ #if defined(CONFIG_SDL)
+         sdl_display_init(ds, full_screen);
+@@ -7626,7 +7635,7 @@
+         }
+     }
+-    if (vnc_display == -1) {
++    if (vnc_display == NULL && vncunused == 0) {
+         gui_timer = qemu_new_timer(rt_clock, gui_update, NULL);
+         qemu_mod_timer(gui_timer, qemu_get_clock(rt_clock));
+     }
 Index: ioemu/vl.h
 ===================================================================
---- ioemu.orig/vl.h    2007-05-03 10:24:06.000000000 +0100
-+++ ioemu/vl.h 2007-05-03 10:24:06.000000000 +0100
-@@ -785,7 +785,7 @@
+--- ioemu.orig/vl.h    2007-05-09 14:12:03.000000000 +0100
++++ ioemu/vl.h 2007-05-09 14:12:16.000000000 +0100
+@@ -928,7 +928,7 @@
  void cocoa_display_init(DisplayState *ds, int full_screen);
  
  /* vnc.c */
--void vnc_display_init(DisplayState *ds, int display);
-+int vnc_display_init(DisplayState *ds, int display, int find_unused);
+-void vnc_display_init(DisplayState *ds, const char *display);
++int vnc_display_init(DisplayState *ds, const char *display, int find_unused);
+ void do_info_vnc(void);
  int vnc_start_viewer(int port);
  
- /* ide.c */
index d7efdb05b3911d56d087e8c9f6ddbdaf71dcd2d3..f8a0063f998c4c3180d4ac5b3ad58bdca695eebc 100644 (file)
@@ -8,8 +8,8 @@ Signed-off-by:  Anthony Liguori <aliguori@us.ibm.com>
 
 Index: ioemu/vnc.c
 ===================================================================
---- ioemu.orig/vnc.c   2007-05-02 14:03:41.000000000 +0100
-+++ ioemu/vnc.c        2007-05-02 14:03:42.000000000 +0100
+--- ioemu.orig/vnc.c   2007-05-09 14:12:44.000000000 +0100
++++ ioemu/vnc.c        2007-05-09 14:12:45.000000000 +0100
 @@ -54,12 +54,12 @@
  {
      size_t capacity;
@@ -34,7 +34,7 @@ Index: ioemu/vnc.c
      int depth; /* internal VNC frame buffer byte per pixel */
      int has_resize;
      int has_hextile;
-@@ -140,7 +140,7 @@
+@@ -165,7 +165,7 @@
  static void vnc_update_client(void *opaque);
  static void vnc_client_read(void *opaque);
  static void framebuffer_set_updated(VncState *vs, int x, int y, int w, int h);
@@ -43,7 +43,7 @@ Index: ioemu/vnc.c
  static void set_seed(unsigned int *seedp);
  static void get_random(int len, unsigned char *buf);
  
-@@ -330,7 +330,7 @@
+@@ -357,7 +357,7 @@
  static void send_framebuffer_update_raw(VncState *vs, int x, int y, int w, int h)
  {
      int i;
@@ -52,7 +52,7 @@ Index: ioemu/vnc.c
  
      vnc_framebuffer_update(vs, x, y, w, h, 0);
  
-@@ -394,9 +394,9 @@
+@@ -421,9 +421,9 @@
  static void vnc_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int dst_y, int w, int h)
  {
      int src, dst;
@@ -65,7 +65,7 @@ Index: ioemu/vnc.c
      int y = 0;
      int pitch = ds->linesize;
      VncState *vs = ds->opaque;
-@@ -465,8 +465,8 @@
+@@ -492,8 +492,8 @@
      VncState *vs = opaque;
      int64_t now;
      int y;
@@ -76,7 +76,7 @@ Index: ioemu/vnc.c
      uint64_t width_mask;
      int n_rectangles;
      int saved_offset;
-@@ -491,7 +491,7 @@
+@@ -518,7 +518,7 @@
      for (y = 0; y < vs->ds->height; y++) {
        if (vs->dirty_row[y] & width_mask) {
            int x;
@@ -85,7 +85,7 @@ Index: ioemu/vnc.c
  
            ptr = row;
            old_ptr = old_row;
-@@ -654,7 +654,7 @@
+@@ -681,7 +681,7 @@
      return buffer->offset == 0;
  }
  
@@ -94,16 +94,7 @@ Index: ioemu/vnc.c
  {
      return buffer->buffer + buffer->offset;
  }
-@@ -778,7 +778,7 @@
- static void vnc_write_u16(VncState *vs, uint16_t value)
- {
--    char buf[2];
-+    uint8_t buf[2];
-     buf[0] = (value >> 8) & 0xFF;
-     buf[1] = value & 0xFF;
-@@ -788,7 +788,7 @@
+@@ -815,7 +815,7 @@
  
  static void vnc_write_u8(VncState *vs, uint8_t value)
  {
@@ -112,35 +103,7 @@ Index: ioemu/vnc.c
  }
  
  static void vnc_flush(VncState *vs)
-@@ -797,23 +797,23 @@
-       vnc_client_write(vs);
- }
--static uint8_t read_u8(char *data, size_t offset)
-+static uint8_t read_u8(uint8_t *data, size_t offset)
- {
-     return data[offset];
- }
--static uint16_t read_u16(char *data, size_t offset)
-+static uint16_t read_u16(uint8_t *data, size_t offset)
- {
-     return ((data[offset] & 0xFF) << 8) | (data[offset + 1] & 0xFF);
- }
--static int32_t read_s32(char *data, size_t offset)
-+static int32_t read_s32(uint8_t *data, size_t offset)
- {
-     return (int32_t)((data[offset] << 24) | (data[offset + 1] << 16) |
-                    (data[offset + 2] << 8) | data[offset + 3]);
- }
--static uint32_t read_u32(char *data, size_t offset)
-+static uint32_t read_u32(uint8_t *data, size_t offset)
- {
-     return ((data[offset] << 24) | (data[offset + 1] << 16) |
-           (data[offset + 2] << 8) | data[offset + 3]);
-@@ -1115,11 +1115,10 @@
+@@ -1139,11 +1139,10 @@
      vga_hw_update();
  }
  
@@ -153,7 +116,7 @@ Index: ioemu/vnc.c
  
      switch (data[0]) {
      case 0:
-@@ -1188,7 +1187,7 @@
+@@ -1212,7 +1211,7 @@
                return 8 + v;
        }
  
@@ -162,7 +125,7 @@ Index: ioemu/vnc.c
        break;
      default:
        printf("Msg: %d\n", data[0]);
-@@ -1200,7 +1199,7 @@
+@@ -1224,7 +1223,7 @@
      return 0;
  }
  
@@ -171,7 +134,7 @@ Index: ioemu/vnc.c
  {
      size_t l;
      char pad[3] = { 0, 0, 0 };
-@@ -1261,7 +1260,7 @@
+@@ -1285,7 +1284,7 @@
      return 0;
  }
  
@@ -180,7 +143,7 @@ Index: ioemu/vnc.c
  {
      extern char vncpasswd[64];
      extern unsigned char challenge[AUTHCHALLENGESIZE];
-@@ -1299,7 +1298,7 @@
+@@ -1323,7 +1322,7 @@
      return 0;
  }
  
@@ -189,7 +152,7 @@ Index: ioemu/vnc.c
  {
      extern char vncpasswd[64];
      extern unsigned char challenge[AUTHCHALLENGESIZE];
-@@ -1474,7 +1473,7 @@
+@@ -1538,7 +1537,7 @@
  
  unsigned int seed;
  
@@ -200,8 +163,8 @@ Index: ioemu/vnc.c
      set_seed(&seed);
 Index: ioemu/vnchextile.h
 ===================================================================
---- ioemu.orig/vnchextile.h    2007-05-02 14:03:13.000000000 +0100
-+++ ioemu/vnchextile.h 2007-05-02 14:03:42.000000000 +0100
+--- ioemu.orig/vnchextile.h    2007-05-09 14:12:15.000000000 +0100
++++ ioemu/vnchextile.h 2007-05-09 14:12:45.000000000 +0100
 @@ -13,7 +13,7 @@
                                               uint32_t *last_fg32,
                                               int *has_bg, int *has_fg)
@@ -211,12 +174,3 @@ Index: ioemu/vnchextile.h
      pixel_t *irow = (pixel_t *)row;
      int j, i;
      pixel_t *last_bg = (pixel_t *)last_bg32;
-@@ -119,7 +119,7 @@
-       for (j = 0; j < h; j++) {
-           int has_color = 0;
-           int min_x = -1;
--          pixel_t color;
-+          pixel_t color = 0;
-           for (i = 0; i < w; i++) {
-               if (!has_color) {
index c7f8364eaa96f8fdc0e5c37905c7caa2d0e657ae..b3f408cdc2b8f644192c2052a7f43a2eb99c0822 100644 (file)
@@ -1,8 +1,8 @@
 Index: ioemu/vnc.c
 ===================================================================
---- ioemu.orig/vnc.c   2007-05-02 10:47:41.000000000 +0100
-+++ ioemu/vnc.c        2007-05-02 10:47:42.000000000 +0100
-@@ -1317,7 +1317,7 @@
+--- ioemu.orig/vnc.c   2007-05-03 20:53:32.000000000 +0100
++++ ioemu/vnc.c        2007-05-03 20:53:59.000000000 +0100
+@@ -1341,7 +1341,7 @@
  
  
      support = 0;
index 5017304c4a5bdd269dd0badc4963a56596be3208..65447d066a363a8120874f1d0e98c9b0d715b4e9 100644 (file)
@@ -1,8 +1,8 @@
 Index: ioemu/vl.c
 ===================================================================
---- ioemu.orig/vl.c    2007-05-03 10:24:05.000000000 +0100
-+++ ioemu/vl.c 2007-05-03 10:24:05.000000000 +0100
-@@ -6597,8 +6597,10 @@
+--- ioemu.orig/vl.c    2007-05-03 19:46:19.000000000 +0100
++++ ioemu/vl.c 2007-05-03 19:46:21.000000000 +0100
+@@ -7616,8 +7616,10 @@
          }
      }
  
@@ -17,8 +17,8 @@ Index: ioemu/vl.c
      if (use_gdbstub) {
 Index: ioemu/vnc.c
 ===================================================================
---- ioemu.orig/vnc.c   2007-05-03 10:24:05.000000000 +0100
-+++ ioemu/vnc.c        2007-05-03 10:24:05.000000000 +0100
+--- ioemu.orig/vnc.c   2007-05-03 19:46:19.000000000 +0100
++++ ioemu/vnc.c        2007-05-03 19:49:33.000000000 +0100
 @@ -3,6 +3,7 @@
   * 
   * Copyright (C) 2006 Anthony Liguori <anthony@codemonkey.ws>
@@ -52,7 +52,7 @@ Index: ioemu/vnc.c
      char *old_data;
      int depth; /* internal VNC frame buffer byte per pixel */
      int has_resize;
-@@ -81,13 +88,25 @@
+@@ -88,12 +95,26 @@
  
      VncReadEvent *read_handler;
      size_t read_handler_expect;
@@ -63,23 +63,23 @@ Index: ioemu/vnc.c
 +    int visible_h;
 +
 +    int slow_client;
++
+     /* input */
+     uint8_t modifiers_state[256];
  };
  
+ static VncState *vnc_state; /* needed for info vnc */
 +#define DIRTY_PIXEL_BITS 64
 +#define X2DP_DOWN(vs, x) ((x) >> (vs)->dirty_pixel_shift)
 +#define X2DP_UP(vs, x) \
 +  (((x) + (1ULL << (vs)->dirty_pixel_shift) - 1) >> (vs)->dirty_pixel_shift)
 +#define DP2X(vs, x) ((x) << (vs)->dirty_pixel_shift)
 +
- /* TODO
-    1) Get the queue working for IO.
-    2) there is some weirdness when using the -S option (the screen is grey
-       and not totally invalidated
--   3) resolutions > 1024
- */
- static void vnc_write(VncState *vs, const void *data, size_t len);
-@@ -96,9 +115,12 @@
+ void do_info_vnc(void)
+ {
+     if (vnc_state == NULL)
+@@ -123,9 +144,12 @@
  static void vnc_write_u16(VncState *vs, uint16_t value);
  static void vnc_write_u8(VncState *vs, uint8_t value);
  static void vnc_flush(VncState *vs);
@@ -92,7 +92,7 @@ Index: ioemu/vnc.c
  static inline void vnc_set_bit(uint32_t *d, int k)
  {
      d[k >> 5] |= 1 << (k & 0x1f);
-@@ -139,20 +161,37 @@
+@@ -166,20 +190,37 @@
      }
      return 0;
  }
@@ -136,9 +136,9 @@ Index: ioemu/vnc.c
  }
  
  static void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
-@@ -169,16 +208,23 @@
- static void vnc_dpy_resize(DisplayState *ds, int w, int h)
+@@ -197,16 +238,23 @@
  {
+     int size_changed;
      VncState *vs = ds->opaque;
 +    int o;
  
@@ -159,10 +159,10 @@ Index: ioemu/vnc.c
 +        ds->depth = vs->depth * 8;
 +        set_color_table(ds);
 +    }
+     size_changed = ds->width != w || ds->height != h;
      ds->width = w;
      ds->height = h;
-     ds->linesize = w * vs->depth;
-@@ -191,6 +237,10 @@
+@@ -220,6 +268,10 @@
        vs->width = ds->width;
        vs->height = ds->height;
      }
@@ -173,7 +173,7 @@ Index: ioemu/vnc.c
  }
  
  /* fastest code */
-@@ -326,8 +376,20 @@
+@@ -355,8 +407,20 @@
      int y = 0;
      int pitch = ds->linesize;
      VncState *vs = ds->opaque;
@@ -195,7 +195,7 @@ Index: ioemu/vnc.c
  
      if (dst_y > src_y) {
        y = h - 1;
-@@ -349,31 +411,34 @@
+@@ -378,31 +442,34 @@
        old_row += pitch;
      }
  
@@ -242,7 +242,7 @@ Index: ioemu/vnc.c
  {
      VncState *vs = opaque;
      int64_t now = qemu_get_clock(rt_clock);
-@@ -382,14 +447,18 @@
+@@ -411,14 +478,18 @@
        int y;
        char *row;
        char *old_row;
@@ -264,7 +264,7 @@ Index: ioemu/vnc.c
  
        /* Walk through the dirty map and eliminate tiles that
           really aren't dirty */
-@@ -397,23 +466,25 @@
+@@ -426,23 +497,25 @@
        old_row = vs->old_data;
  
        for (y = 0; y < vs->ds->height; y++) {
@@ -299,7 +299,7 @@ Index: ioemu/vnc.c
                }
            }
  
-@@ -421,7 +492,8 @@
+@@ -450,7 +523,8 @@
            old_row += vs->ds->linesize;
        }
  
@@ -309,7 +309,7 @@ Index: ioemu/vnc.c
            return;
  
        /* Count rectangles */
-@@ -431,34 +503,56 @@
+@@ -460,34 +534,56 @@
        saved_offset = vs->output.offset;
        vnc_write_u16(vs, 0);
  
@@ -377,7 +377,7 @@ Index: ioemu/vnc.c
  }
  
  static void vnc_timer_init(VncState *vs)
-@@ -469,8 +563,6 @@
+@@ -498,8 +594,6 @@
  
  static void vnc_dpy_refresh(DisplayState *ds)
  {
@@ -386,7 +386,7 @@ Index: ioemu/vnc.c
      vga_hw_update();
  }
  
-@@ -506,7 +598,7 @@
+@@ -535,7 +629,7 @@
  
  static void buffer_reset(Buffer *buffer)
  {
@@ -395,7 +395,7 @@ Index: ioemu/vnc.c
  }
  
  static void buffer_append(Buffer *buffer, const void *data, size_t len)
-@@ -547,12 +639,12 @@
+@@ -576,12 +670,12 @@
      if (!ret)
        return;
  
@@ -411,7 +411,7 @@ Index: ioemu/vnc.c
  }
  
  static void vnc_read_when(VncState *vs, VncReadEvent *func, size_t expecting)
-@@ -584,11 +676,11 @@
+@@ -613,11 +707,11 @@
            return;
  
        if (!ret) {
@@ -426,7 +426,7 @@ Index: ioemu/vnc.c
      }
  }
  
-@@ -596,9 +688,9 @@
+@@ -625,9 +719,9 @@
  {
      buffer_reserve(&vs->output, len);
  
@@ -439,7 +439,7 @@ Index: ioemu/vnc.c
  
      buffer_append(&vs->output, data, len);
  }
-@@ -720,22 +812,25 @@
+@@ -848,22 +942,25 @@
      do_key_event(vs, down, sym);
  }
  
@@ -476,7 +476,7 @@ Index: ioemu/vnc.c
  
      qemu_mod_timer(vs->timer, qemu_get_clock(rt_clock));
  }
-@@ -843,8 +938,6 @@
+@@ -978,8 +1075,6 @@
      }
  
      vnc_dpy_resize(vs->ds, vs->ds->width, vs->ds->height);
@@ -485,7 +485,7 @@ Index: ioemu/vnc.c
  
      vga_hw_invalidate();
      vga_hw_update();
-@@ -924,6 +1017,8 @@
+@@ -1059,6 +1154,8 @@
  {
      char pad[3] = { 0, 0, 0 };
  
@@ -494,7 +494,7 @@ Index: ioemu/vnc.c
      vs->width = vs->ds->width;
      vs->height = vs->ds->height;
      vnc_write_u16(vs, vs->ds->width);
-@@ -1010,11 +1105,11 @@
+@@ -1145,11 +1242,11 @@
        vnc_write(vs, "RFB 003.003\n", 12);
        vnc_flush(vs);
        vnc_read_when(vs, protocol_version, 12);
@@ -508,32 +508,20 @@ Index: ioemu/vnc.c
      }
  }
  
-@@ -1071,17 +1166,15 @@
-       exit(1);
-     }
--    ret = qemu_set_fd_handler2(vs->lsock, vnc_listen_poll, vnc_listen_read, NULL, vs);
--    if (ret == -1) {
-+    ret = qemu_set_fd_handler2(vs->lsock, vnc_listen_poll, vnc_listen_read,
-+                             NULL, vs);
-+    if (ret == -1)
-       exit(1);
--    }
-     vs->ds->data = NULL;
-     vs->ds->dpy_update = vnc_dpy_update;
+@@ -1195,8 +1292,6 @@
      vs->ds->dpy_resize = vnc_dpy_resize;
      vs->ds->dpy_refresh = vnc_dpy_refresh;
  
 -    memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));
 -
      vnc_dpy_resize(vs->ds, 640, 400);
- }
+ #ifndef _WIN32
 Index: ioemu/vl.h
 ===================================================================
---- ioemu.orig/vl.h    2007-05-03 10:24:05.000000000 +0100
-+++ ioemu/vl.h 2007-05-03 10:24:05.000000000 +0100
-@@ -319,6 +319,7 @@
+--- ioemu.orig/vl.h    2007-05-03 19:36:00.000000000 +0100
++++ ioemu/vl.h 2007-05-03 19:46:21.000000000 +0100
+@@ -356,6 +356,7 @@
  int is_graphic_console(void);
  CharDriverState *text_console_init(DisplayState *ds);
  void console_select(unsigned int index);
index d8051a151aa78b2977b7628dd4ea40ac36f17253..9dfda749234fc5f0416f92d6603957420d44a891 100644 (file)
@@ -20,9 +20,9 @@ Signed-off-by:  Daniel P. Berrange <berrange@redhat.com>
 
 Index: ioemu/vl.c
 ===================================================================
---- ioemu.orig/vl.c    2007-05-03 10:24:06.000000000 +0100
-+++ ioemu/vl.c 2007-05-03 10:24:06.000000000 +0100
-@@ -123,6 +123,7 @@
+--- ioemu.orig/vl.c    2007-05-09 14:12:16.000000000 +0100
++++ ioemu/vl.c 2007-05-09 14:12:43.000000000 +0100
+@@ -133,6 +133,7 @@
  int nographic;
  int vncviewer;
  int vncunused;
@@ -30,7 +30,7 @@ Index: ioemu/vl.c
  const char* keyboard_layout = NULL;
  int64_t ticks_per_sec;
  int boot_device = 'c';
-@@ -2831,10 +2832,22 @@
+@@ -3008,10 +3009,22 @@
      return -1;
  }
  
@@ -54,7 +54,7 @@ Index: ioemu/vl.c
      const char *p, *r;
      int port;
  
-@@ -2845,14 +2858,8 @@
+@@ -3022,14 +3035,8 @@
      if (buf[0] == '\0') {
          saddr->sin_addr.s_addr = 0;
      } else {
@@ -71,15 +71,15 @@ Index: ioemu/vl.c
      }
      port = strtol(p, (char **)&r, 0);
      if (r == p)
-@@ -5419,6 +5426,7 @@
+@@ -6313,6 +6320,7 @@
           "-vnc display    start a VNC server on display\n"
             "-vncviewer      start a vncviewer process for this domain\n"
             "-vncunused      bind the VNC server to an unused port\n"
 +           "-vnclisten      bind the VNC server to this address\n"
-            "-acpi           disable or enable ACPI of HVM domain \n"
-            "\n"
-            "During emulation, the following keys are useful:\n"
-@@ -5507,6 +5515,7 @@
+ #ifndef _WIN32
+          "-daemonize      daemonize QEMU after initializing\n"
+ #endif
+@@ -6410,6 +6418,7 @@
      QEMU_OPTION_acpi,
      QEMU_OPTION_vncviewer,
      QEMU_OPTION_vncunused,
@@ -87,15 +87,15 @@ Index: ioemu/vl.c
  };
  
  typedef struct QEMUOption {
-@@ -5583,6 +5592,7 @@
+@@ -6490,6 +6499,7 @@
      { "vnc", HAS_ARG, QEMU_OPTION_vnc },
      { "vncviewer", 0, QEMU_OPTION_vncviewer },
      { "vncunused", 0, QEMU_OPTION_vncunused },
 +    { "vnclisten", HAS_ARG, QEMU_OPTION_vnclisten },
-     
      /* temporary options */
      { "usb", 0, QEMU_OPTION_usb },
-@@ -5974,6 +5984,8 @@
+@@ -6889,6 +6899,8 @@
  
      nb_nics = 0;
      /* default mac address of the first network interface */
@@ -104,9 +104,9 @@ Index: ioemu/vl.c
      
      /* init debug */
      sprintf(qemu_dm_logfilename, "/var/log/xen/qemu-dm.%ld.log", (long)getpid());
-@@ -6346,6 +6358,9 @@
-                 if (vnc_display == -1)
-                     vnc_display = 0;
+@@ -7280,6 +7292,9 @@
+             case QEMU_OPTION_vncunused:
+                 vncunused++;
                  break;
 +            case QEMU_OPTION_vnclisten:
 +                parse_host(&vnclisten_addr, optarg);
@@ -114,19 +114,20 @@ Index: ioemu/vl.c
              }
          }
      }
-@@ -6547,7 +6562,7 @@
-     if (nographic) {
+@@ -7563,7 +7578,8 @@
          dumb_display_init(ds);
-     } else if (vnc_display != -1) {
--      vnc_display = vnc_display_init(ds, vnc_display, vncunused);
-+      vnc_display = vnc_display_init(ds, vnc_display, vncunused, &vnclisten_addr);
+     } else if (vnc_display != NULL || vncunused != 0) {
+       int vnc_display_port;
+-      vnc_display_port = vnc_display_init(ds, vnc_display, vncunused);
++      vnc_display_port = vnc_display_init(ds, vnc_display, vncunused,
++                                          &vnclisten_addr);
        if (vncviewer)
-           vnc_start_viewer(vnc_display);
+           vnc_start_viewer(vnc_display_port);
      } else {
 Index: ioemu/vl.h
 ===================================================================
---- ioemu.orig/vl.h    2007-05-03 10:24:06.000000000 +0100
-+++ ioemu/vl.h 2007-05-03 10:24:06.000000000 +0100
+--- ioemu.orig/vl.h    2007-05-09 14:12:16.000000000 +0100
++++ ioemu/vl.h 2007-05-09 14:12:43.000000000 +0100
 @@ -37,6 +37,8 @@
  #include <unistd.h>
  #include <fcntl.h>
@@ -136,42 +137,72 @@ Index: ioemu/vl.h
  #include "xenctrl.h"
  #include "xs.h"
  #include <xen/hvm/e820.h>
-@@ -785,7 +787,7 @@
+@@ -928,7 +930,7 @@
  void cocoa_display_init(DisplayState *ds, int full_screen);
  
  /* vnc.c */
--int vnc_display_init(DisplayState *ds, int display, int find_unused);
-+int vnc_display_init(DisplayState *ds, int display, int find_unused, struct sockaddr_in *addr);
+-int vnc_display_init(DisplayState *ds, const char *display, int find_unused);
++int vnc_display_init(DisplayState *ds, const char *display, int find_unused, struct sockaddr_in *iaddr);
+ void do_info_vnc(void);
  int vnc_start_viewer(int port);
  
- /* ide.c */
 Index: ioemu/vnc.c
 ===================================================================
---- ioemu.orig/vnc.c   2007-05-03 10:24:06.000000000 +0100
-+++ ioemu/vnc.c        2007-05-03 10:24:06.000000000 +0100
-@@ -1197,9 +1197,8 @@
-     }
- }
+--- ioemu.orig/vnc.c   2007-05-09 14:12:21.000000000 +0100
++++ ioemu/vnc.c        2007-05-09 14:12:43.000000000 +0100
+@@ -1270,10 +1270,9 @@
+ extern int parse_host_port(struct sockaddr_in *saddr, const char *str);
  
--int vnc_display_init(DisplayState *ds, int display, int find_unused)
-+int vnc_display_init(DisplayState *ds, int display, int find_unused, struct sockaddr_in *addr)
+-int vnc_display_init(DisplayState *ds, const char *arg, int find_unused)
++int vnc_display_init(DisplayState *ds, const char *arg, int find_unused, struct sockaddr_in *iaddr)
  {
--    struct sockaddr_in addr;
-     int reuse_addr, ret;
-     VncState *vs;
+     struct sockaddr *addr;
+-    struct sockaddr_in iaddr;
+ #ifndef _WIN32
+     struct sockaddr_un uaddr;
+ #endif
+@@ -1334,8 +1333,8 @@
+     } else
+ #endif
+     {
+-      addr = (struct sockaddr *)&iaddr;
+-      addrlen = sizeof(iaddr);
++      addr = (struct sockaddr *)iaddr;
++      addrlen = sizeof(*iaddr);
  
-@@ -1237,11 +1236,10 @@
-     }
+       vs->lsock = socket(PF_INET, SOCK_STREAM, 0);
+       if (vs->lsock == -1) {
+@@ -1343,12 +1342,12 @@
+           exit(1);
+       }
  
-  retry:
--    addr.sin_family = AF_INET;
--    addr.sin_port = htons(5900 + display);
--    memset(&addr.sin_addr, 0, sizeof(addr.sin_addr));
-+    addr->sin_family = AF_INET;
-+    addr->sin_port = htons(5900 + display);
+-      if (parse_host_port(&iaddr, arg) < 0) {
++      if (parse_host_port(iaddr, arg) < 0) {
+           fprintf(stderr, "Could not parse VNC address\n");
+           exit(1);
+       }
+           
+-      iaddr.sin_port = htons(ntohs(iaddr.sin_port) + 5900);
++      iaddr->sin_port = htons(ntohs(iaddr->sin_port) + 5900);
  
--    if (bind(vs->lsock, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
-+    if (bind(vs->lsock, (struct sockaddr *)addr, sizeof(struct sockaddr_in)) == -1) {
+       reuse_addr = 1;
+       ret = setsockopt(vs->lsock, SOL_SOCKET, SO_REUSEADDR,
+@@ -1361,7 +1360,7 @@
+     while (bind(vs->lsock, addr, addrlen) == -1) {
        if (find_unused && errno == EADDRINUSE) {
-           display++;
-           goto retry;
+-          iaddr.sin_port = htons(ntohs(iaddr.sin_port) + 1);
++          iaddr->sin_port = htons(ntohs(iaddr->sin_port) + 1);
+           continue;
+       }
+       fprintf(stderr, "bind() failed\n");
+@@ -1378,7 +1377,7 @@
+       exit(1);
+     }
+-    return ntohs(iaddr.sin_port);
++    return ntohs(iaddr->sin_port);
+ }
+ int vnc_start_viewer(int port)
index 3716b691c38d14cccd5107e7db06d1121df5cbd1..620854225d2ba2a6e77678c16a95fd8820ce793a 100644 (file)
@@ -17,31 +17,31 @@ Signed-off-by: Masami Watanabe <masami.watanabe@jp.fujitsu.com>
 
 Index: ioemu/Makefile.target
 ===================================================================
---- ioemu.orig/Makefile.target 2007-05-03 15:23:43.000000000 +0100
-+++ ioemu/Makefile.target      2007-05-03 15:23:43.000000000 +0100
-@@ -407,6 +407,7 @@
- VL_OBJS+=sdl.o
+--- ioemu.orig/Makefile.target 2007-05-09 14:12:44.000000000 +0100
++++ ioemu/Makefile.target      2007-05-09 14:12:44.000000000 +0100
+@@ -443,6 +443,7 @@
+ VL_OBJS+=sdl.o x_keymap.o
  endif
  VL_OBJS+=vnc.o
 +VL_OBJS+=d3des.o
  ifdef CONFIG_COCOA
  VL_OBJS+=cocoa.o
  COCOA_LIBS=-F/System/Library/Frameworks -framework Cocoa -framework IOKit
-@@ -467,6 +468,9 @@
+@@ -503,6 +504,9 @@
  vnc.o: vnc.c keymaps.c sdl_keysym.h vnchextile.h
-       $(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
+       $(CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
  
 +d3des.o: d3des.c d3des.h
 +      $(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
 +
  sdlaudio.o: sdlaudio.c
-       $(CC) $(CFLAGS) $(DEFINES) $(SDL_CFLAGS) -c -o $@ $<
+       $(CC) $(CFLAGS) $(CPPFLAGS) $(SDL_CFLAGS) $(BASE_CFLAGS) -c -o $@ $<
  
 Index: ioemu/vl.c
 ===================================================================
---- ioemu.orig/vl.c    2007-05-03 15:23:43.000000000 +0100
-+++ ioemu/vl.c 2007-05-03 15:23:43.000000000 +0100
-@@ -172,6 +172,9 @@
+--- ioemu.orig/vl.c    2007-05-09 14:12:44.000000000 +0100
++++ ioemu/vl.c 2007-05-09 14:12:44.000000000 +0100
+@@ -189,6 +189,9 @@
  char domain_name[1024] = { 'H','V', 'M', 'X', 'E', 'N', '-'};
  extern int domid;
  
@@ -51,7 +51,7 @@ Index: ioemu/vl.c
  /***********************************************************/
  /* x86 ISA bus support */
  
-@@ -5982,6 +5985,7 @@
+@@ -6897,6 +6900,7 @@
      vncunused = 0;
      kernel_filename = NULL;
      kernel_cmdline = "";
@@ -59,7 +59,7 @@ Index: ioemu/vl.c
  #ifndef CONFIG_DM
  #ifdef TARGET_PPC
      cdrom_index = 1;
-@@ -6627,6 +6631,10 @@
+@@ -7644,6 +7648,10 @@
  
      init_ioports();
  
@@ -72,9 +72,9 @@ Index: ioemu/vl.c
          dumb_display_init(ds);
 Index: ioemu/vl.h
 ===================================================================
---- ioemu.orig/vl.h    2007-05-03 15:23:43.000000000 +0100
-+++ ioemu/vl.h 2007-05-03 15:23:43.000000000 +0100
-@@ -1215,6 +1215,7 @@
+--- ioemu.orig/vl.h    2007-05-09 14:12:44.000000000 +0100
++++ ioemu/vl.h 2007-05-09 14:12:44.000000000 +0100
+@@ -1434,6 +1434,7 @@
  void xenstore_process_event(void *opaque);
  void xenstore_check_new_media_present(int timeout);
  void xenstore_write_vncport(int vnc_display);
@@ -82,7 +82,7 @@ Index: ioemu/vl.h
  
  int xenstore_vm_write(int domid, char *key, char *val);
  char *xenstore_vm_read(int domid, char *key, int *len);
-@@ -1233,4 +1234,7 @@
+@@ -1452,4 +1453,7 @@
  
  void destroy_hvm_domain(void);
  
@@ -92,8 +92,8 @@ Index: ioemu/vl.h
  #endif /* VL_H */
 Index: ioemu/vnc.c
 ===================================================================
---- ioemu.orig/vnc.c   2007-05-03 15:22:57.000000000 +0100
-+++ ioemu/vnc.c        2007-05-03 15:23:43.000000000 +0100
+--- ioemu.orig/vnc.c   2007-05-09 14:12:43.000000000 +0100
++++ ioemu/vnc.c        2007-05-09 14:12:44.000000000 +0100
 @@ -44,6 +44,7 @@
  
  #include "vnc_keysym.h"
@@ -102,7 +102,7 @@ Index: ioemu/vnc.c
  
  #define XK_MISCELLANY
  #define XK_LATIN1
-@@ -137,6 +138,9 @@
+@@ -164,6 +165,9 @@
  static void vnc_update_client(void *opaque);
  static void vnc_client_read(void *opaque);
  static void framebuffer_set_updated(VncState *vs, int x, int y, int w, int h);
@@ -112,7 +112,7 @@ Index: ioemu/vnc.c
  
  #if 0
  static inline void vnc_set_bit(uint32_t *d, int k)
-@@ -1210,23 +1214,92 @@
+@@ -1281,23 +1285,92 @@
      return 0;
  }
  
@@ -209,7 +209,7 @@ Index: ioemu/vnc.c
  
      return 0;
  }
-@@ -1350,3 +1423,32 @@
+@@ -1462,3 +1535,32 @@
        return pid;
      }
  }
@@ -244,8 +244,8 @@ Index: ioemu/vnc.c
 +}
 Index: ioemu/xenstore.c
 ===================================================================
---- ioemu.orig/xenstore.c      2007-05-03 15:23:43.000000000 +0100
-+++ ioemu/xenstore.c   2007-05-03 15:24:09.000000000 +0100
+--- ioemu.orig/xenstore.c      2007-05-09 14:12:43.000000000 +0100
++++ ioemu/xenstore.c   2007-05-09 14:12:44.000000000 +0100
 @@ -253,6 +253,57 @@
      free(buf);
  }
@@ -307,7 +307,7 @@ Index: ioemu/xenstore.c
 Index: ioemu/d3des.c
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ ioemu/d3des.c      2007-05-03 15:23:43.000000000 +0100
++++ ioemu/d3des.c      2007-05-09 14:12:44.000000000 +0100
 @@ -0,0 +1,434 @@
 +/*
 + * This is D3DES (V5.09) by Richard Outerbridge with the double and
@@ -746,7 +746,7 @@ Index: ioemu/d3des.c
 Index: ioemu/d3des.h
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ ioemu/d3des.h      2007-05-03 15:23:43.000000000 +0100
++++ ioemu/d3des.h      2007-05-09 14:12:44.000000000 +0100
 @@ -0,0 +1,51 @@
 +/*
 + * This is D3DES (V5.09) by Richard Outerbridge with the double and
index 7eaa4dfc4b3fc3289bff150ad16101afc904ac32..82ef0009738fe20fab7e93127d6d3e77b3795f8f 100644 (file)
@@ -9,8 +9,8 @@ Signed-off-by: Steven Smith <sos22@cam.ac.uk>
 
 Index: ioemu/vnc.c
 ===================================================================
---- ioemu.orig/vnc.c   2006-12-06 23:46:11.000000000 +0000
-+++ ioemu/vnc.c        2006-12-06 23:46:11.000000000 +0000
+--- ioemu.orig/vnc.c   2007-05-03 19:49:33.000000000 +0100
++++ ioemu/vnc.c        2007-05-03 19:49:43.000000000 +0100
 @@ -26,6 +26,7 @@
  
  #include "vl.h"
@@ -19,7 +19,7 @@ Index: ioemu/vnc.c
  
  #define VNC_REFRESH_INTERVAL (1000 / 30)
  
-@@ -679,8 +680,10 @@
+@@ -710,8 +711,10 @@
            memmove(vs->input.buffer, vs->input.buffer + len,
                    vs->input.offset - len);
            vs->input.offset -= len;
@@ -31,7 +31,7 @@ Index: ioemu/vnc.c
      }
  }
  
-@@ -963,8 +966,12 @@
+@@ -1100,8 +1103,12 @@
        if (len == 1)
            return 4;
  
@@ -46,7 +46,7 @@ Index: ioemu/vnc.c
  
        limit = read_u16(data, 2);
        for (i = 0; i < limit; i++) {
-@@ -998,8 +1005,12 @@
+@@ -1135,8 +1142,12 @@
        if (len == 1)
            return 8;
  
index 672cada92b2a4852ac52a433d9ae9cbce6c96e87..21d4343047d6ebf5912870cc546d64cb7472b325 100644 (file)
@@ -1,10 +1,10 @@
 Index: ioemu/vnc.c
 ===================================================================
---- ioemu.orig/vnc.c   2007-05-03 10:24:06.000000000 +0100
-+++ ioemu/vnc.c        2007-05-03 10:24:06.000000000 +0100
-@@ -1189,3 +1189,31 @@
-     vnc_dpy_resize(vs->ds, 640, 400);
+--- ioemu.orig/vnc.c   2007-05-03 19:49:43.000000000 +0100
++++ ioemu/vnc.c        2007-05-03 19:49:46.000000000 +0100
+@@ -1364,3 +1364,31 @@
+       exit(1);
+     }
  }
 +
 +int vnc_start_viewer(int port)
@@ -36,9 +36,9 @@ Index: ioemu/vnc.c
 +}
 Index: ioemu/vl.c
 ===================================================================
---- ioemu.orig/vl.c    2007-05-03 10:24:05.000000000 +0100
-+++ ioemu/vl.c 2007-05-03 10:24:06.000000000 +0100
-@@ -121,6 +121,7 @@
+--- ioemu.orig/vl.c    2007-05-03 19:46:21.000000000 +0100
++++ ioemu/vl.c 2007-05-03 19:50:04.000000000 +0100
+@@ -131,6 +131,7 @@
  int bios_size;
  static DisplayState display_state;
  int nographic;
@@ -46,15 +46,15 @@ Index: ioemu/vl.c
  const char* keyboard_layout = NULL;
  int64_t ticks_per_sec;
  int boot_device = 'c';
-@@ -5415,6 +5416,7 @@
- #endif
+@@ -6309,6 +6310,7 @@
+            "-no-reboot      exit instead of rebooting\n"
             "-loadvm file    start right away with a saved state (loadvm in monitor)\n"
           "-vnc display    start a VNC server on display\n"
 +           "-vncviewer      start a vncviewer process for this domain\n"
-            "-acpi           disable or enable ACPI of HVM domain \n"
-            "\n"
-            "During emulation, the following keys are useful:\n"
-@@ -5501,6 +5503,7 @@
+ #ifndef _WIN32
+          "-daemonize      daemonize QEMU after initializing\n"
+ #endif
+@@ -6404,6 +6406,7 @@
      QEMU_OPTION_d,
      QEMU_OPTION_vcpus,
      QEMU_OPTION_acpi,
@@ -62,15 +62,15 @@ Index: ioemu/vl.c
  };
  
  typedef struct QEMUOption {
-@@ -5575,6 +5578,7 @@
+@@ -6482,6 +6485,7 @@
      { "usbdevice", HAS_ARG, QEMU_OPTION_usbdevice },
      { "smp", HAS_ARG, QEMU_OPTION_smp },
      { "vnc", HAS_ARG, QEMU_OPTION_vnc },
 +    { "vncviewer", 0, QEMU_OPTION_vncviewer },
-     
      /* temporary options */
      { "usb", 0, QEMU_OPTION_usb },
-@@ -5933,6 +5937,7 @@
+@@ -6848,6 +6852,7 @@
  #endif
      snapshot = 0;
      nographic = 0;
@@ -78,7 +78,7 @@ Index: ioemu/vl.c
      kernel_filename = NULL;
      kernel_cmdline = "";
  #ifdef TARGET_PPC
-@@ -6328,6 +6333,9 @@
+@@ -7264,6 +7269,9 @@
              case QEMU_OPTION_acpi:
                  acpi_enabled = 1;
                  break;
@@ -88,9 +88,9 @@ Index: ioemu/vl.c
              }
          }
      }
-@@ -6530,6 +6538,8 @@
+@@ -7547,6 +7555,8 @@
          dumb_display_init(ds);
-     } else if (vnc_display != -1) {
+     } else if (vnc_display != NULL) {
        vnc_display_init(ds, vnc_display);
 +      if (vncviewer)
 +          vnc_start_viewer(vnc_display);
@@ -99,13 +99,13 @@ Index: ioemu/vl.c
          sdl_display_init(ds, full_screen);
 Index: ioemu/vl.h
 ===================================================================
---- ioemu.orig/vl.h    2007-05-03 10:24:05.000000000 +0100
-+++ ioemu/vl.h 2007-05-03 10:24:06.000000000 +0100
-@@ -786,6 +786,7 @@
+--- ioemu.orig/vl.h    2007-05-03 19:46:21.000000000 +0100
++++ ioemu/vl.h 2007-05-03 19:50:15.000000000 +0100
+@@ -930,6 +930,7 @@
  /* vnc.c */
- void vnc_display_init(DisplayState *ds, int display);
+ void vnc_display_init(DisplayState *ds, const char *display);
+ void do_info_vnc(void);
 +int vnc_start_viewer(int port);
  
- /* ide.c */
- #define MAX_DISKS 4
+ /* x_keymap.c */
+ extern uint8_t _translate_keycode(const int key);
index 0c837147ad848672bd4cfaa742121b872a1344dd..42c010860809c83dfc5fb2209b2a71edded03670 100644 (file)
@@ -1,8 +1,8 @@
 Index: ioemu/vnc.c
 ===================================================================
---- ioemu.orig/vnc.c   2006-12-06 23:46:11.000000000 +0000
-+++ ioemu/vnc.c        2006-12-06 23:46:11.000000000 +0000
-@@ -1026,6 +1026,7 @@
+--- ioemu.orig/vnc.c   2007-05-03 19:49:46.000000000 +0100
++++ ioemu/vnc.c        2007-05-03 19:50:17.000000000 +0100
+@@ -1163,6 +1163,7 @@
  
  static int protocol_client_init(VncState *vs, char *data, size_t len)
  {
@@ -10,7 +10,7 @@ Index: ioemu/vnc.c
      char pad[3] = { 0, 0, 0 };
  
      vga_hw_update();
-@@ -1073,8 +1074,10 @@
+@@ -1210,8 +1211,10 @@
        
      vnc_write(vs, pad, 3);           /* padding */
  
index 64184dd81074eab54878829789c53e0d36656ef0..e83b1e81f932ea4ba73d7e946b4cdf9e797f0106 100644 (file)
@@ -1,8 +1,8 @@
 Index: ioemu/Makefile
 ===================================================================
---- ioemu.orig/Makefile        2007-05-03 15:38:37.000000000 +0100
-+++ ioemu/Makefile     2007-05-03 15:38:39.000000000 +0100
-@@ -1,11 +1,14 @@
+--- ioemu.orig/Makefile        2007-05-09 13:42:55.000000000 +0100
++++ ioemu/Makefile     2007-05-09 13:42:58.000000000 +0100
+@@ -1,6 +1,9 @@
  # Makefile for QEMU.
  
 -include config-host.mak
@@ -13,14 +13,8 @@ Index: ioemu/Makefile
  
  .PHONY: all clean distclean dvi info install install-doc tar tarbin \
        speed test test2 html dvi info
--CFLAGS=-Wall -O2 -g -fno-strict-aliasing -I.
-+CFLAGS+=-Wall -O2 -g -fno-strict-aliasing -I.
- ifdef CONFIG_DARWIN
- CFLAGS+= -mdynamic-no-pic
+@@ -32,9 +35,11 @@
  endif
-@@ -25,9 +28,11 @@
- DOCS=
  endif
  
 +TOOLS=
@@ -32,7 +26,7 @@ Index: ioemu/Makefile
        $(MAKE) -C $(subst subdir-,,$@) all
  
  recurse-all: $(patsubst %,subdir-%, $(TARGET_DIRS))
-@@ -44,7 +49,7 @@
+@@ -51,7 +56,7 @@
        rm -f *.o *.a $(TOOLS) dyngen$(EXESUF) TAGS *.pod *~ */*~
        $(MAKE) -C tests clean
        for d in $(TARGET_DIRS); do \
@@ -41,12 +35,12 @@ Index: ioemu/Makefile
          done
  
  distclean: clean
-@@ -60,24 +65,24 @@
+@@ -67,25 +72,25 @@
  
  install-doc: $(DOCS)
        mkdir -p "$(DESTDIR)$(docdir)"
 -      $(INSTALL) -m 644 qemu-doc.html  qemu-tech.html "$(DESTDIR)$(docdir)"
-+      $(INSTALL_DATA) qemu-doc.html  qemu-tech.html "$(DESTDIR)$(docdir)"
++      $(INSTALL_DATA) -m 644 qemu-doc.html  qemu-tech.html "$(DESTDIR)$(docdir)"
  ifndef CONFIG_WIN32
        mkdir -p "$(DESTDIR)$(mandir)/man1"
 -      $(INSTALL) qemu.1 qemu-img.1 "$(DESTDIR)$(mandir)/man1"
@@ -58,24 +52,26 @@ Index: ioemu/Makefile
 -      $(INSTALL) -m 755 -s $(TOOLS) "$(DESTDIR)$(bindir)"
 -      mkdir -p "$(DESTDIR)$(datadir)"
 -      for x in bios.bin vgabios.bin vgabios-cirrus.bin ppc_rom.bin \
--                      video.x openbios-sparc32 linux_boot.bin; do \
+-              video.x openbios-sparc32 linux_boot.bin pxe-ne2k_pci.bin \
+-              pxe-rtl8139.bin pxe-pcnet.bin; do \
 -              $(INSTALL) -m 644 $(SRC_PATH)/pc-bios/$$x "$(DESTDIR)$(datadir)"; \
 -      done
 +#     $(INSTALL) -m 755 -s $(TOOLS) "$(DESTDIR)$(bindir)"
 +#     mkdir -p "$(DESTDIR)$(datadir)"
 +#     for x in bios.bin vgabios.bin vgabios-cirrus.bin ppc_rom.bin \
-+#                     video.x openbios-sparc32 linux_boot.bin; do \
-+#             $(INSTALL_DATA) $(SRC_PATH)/pc-bios/$$x "$(DESTDIR)$(datadir)"; \
++#             video.x openbios-sparc32 linux_boot.bin pxe-ne2k_pci.bin \
++#             pxe-rtl8139.bin pxe-pcnet.bin; do \
++#             $(INSTALL) -m 644 $(SRC_PATH)/pc-bios/$$x "$(DESTDIR)$(datadir)"; \
 +#     done
  ifndef CONFIG_WIN32
        mkdir -p "$(DESTDIR)$(datadir)/keymaps"
        for x in $(KEYMAPS); do \
 -              $(INSTALL) -m 644 $(SRC_PATH)/keymaps/$$x "$(DESTDIR)$(datadir)/keymaps"; \
-+              $(INSTALL_DATA) $(SRC_PATH)/keymaps/$$x "$(DESTDIR)$(datadir)/keymaps"; \
++              $(INSTALL_DATA) -m 644 $(SRC_PATH)/keymaps/$$x "$(DESTDIR)$(datadir)/keymaps"; \
        done
  endif
        for d in $(TARGET_DIRS); do \
-@@ -89,7 +94,7 @@
+@@ -97,7 +102,7 @@
        $(MAKE) -C tests $@
  
  TAGS: 
@@ -84,7 +80,7 @@ Index: ioemu/Makefile
  
  cscope:
        rm -f ./cscope.*
-@@ -107,11 +112,11 @@
+@@ -115,11 +120,11 @@
        texi2dvi $<
  
  qemu.1: qemu-doc.texi
@@ -100,8 +96,8 @@ Index: ioemu/Makefile
  info: qemu-doc.info qemu-tech.info
 Index: ioemu/Makefile.target
 ===================================================================
---- ioemu.orig/Makefile.target 2007-05-03 15:38:37.000000000 +0100
-+++ ioemu/Makefile.target      2007-05-03 15:38:39.000000000 +0100
+--- ioemu.orig/Makefile.target 2007-05-09 13:42:55.000000000 +0100
++++ ioemu/Makefile.target      2007-05-09 13:42:58.000000000 +0100
 @@ -1,5 +1,8 @@
  include config.mak
  
@@ -111,37 +107,37 @@ Index: ioemu/Makefile.target
  TARGET_BASE_ARCH:=$(TARGET_ARCH)
  ifeq ($(TARGET_ARCH), x86_64)
  TARGET_BASE_ARCH:=i386
-@@ -10,14 +13,21 @@
+@@ -10,9 +13,11 @@
  ifeq ($(TARGET_ARCH), sparc64)
  TARGET_BASE_ARCH:=sparc
  endif
 -TARGET_PATH=$(SRC_PATH)/target-$(TARGET_BASE_ARCH)
 +TARGET_PATH=$(SRC_PATH)/target-$(TARGET_BASE_ARCH)$(TARGET_SUB)
  VPATH=$(SRC_PATH):$(TARGET_PATH):$(SRC_PATH)/hw:$(SRC_PATH)/audio
- DEFINES=-I. -I.. -I$(TARGET_PATH) -I$(SRC_PATH)
-+DEFINES+= -I$(XEN_ROOT)/tools/libxc
-+DEFINES+= -I$(XEN_ROOT)/tools/xenstore
- ifdef CONFIG_USER_ONLY
- VPATH+=:$(SRC_PATH)/linux-user
- DEFINES+=-I$(SRC_PATH)/linux-user -I$(SRC_PATH)/linux-user/$(TARGET_ARCH)
+ CPPFLAGS=-I. -I.. -I$(TARGET_PATH) -I$(SRC_PATH)
++CPPFLAGS+= -I$(XEN_ROOT)/tools/libxc
++CPPFLAGS+= -I$(XEN_ROOT)/tools/xenstore
+ ifdef CONFIG_DARWIN_USER
+ VPATH+=:$(SRC_PATH)/darwin-user
+ CPPFLAGS+=-I$(SRC_PATH)/darwin-user -I$(SRC_PATH)/darwin-user/$(TARGET_ARCH)
+@@ -23,6 +28,10 @@
  endif
--CFLAGS=-Wall -O2 -g -fno-strict-aliasing
-+CFLAGS+=-Wall -O2 -g -fno-strict-aliasing
+ BASE_CFLAGS=
+ BASE_LDFLAGS=
 +SSE2 := $(call cc-option,$(CC),-msse2,)
 +ifeq ($(SSE2),-msse2)
 +CFLAGS += -DUSE_SSE2=1 -msse2
 +endif
-+CFLAGS+= $(LOCAL_CFLAGS)
  #CFLAGS+=-Werror
- LDFLAGS=-g
  LIBS=
-@@ -165,8 +175,12 @@
+ HELPER_CFLAGS=$(CFLAGS)
+@@ -181,8 +190,12 @@
  
  #########################################################
  
--DEFINES+=-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
-+DEFINES+=-D_GNU_SOURCE
-+#-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
+-CPPFLAGS+=-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
++CPPFLAGS+=-D_GNU_SOURCE
++# -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
  LIBS+=-lm
 +LIBS+=-L../../libxc -lxenctrl -lxenguest
 +LIBS+=-L../../xenstore -lxenstore
@@ -149,16 +145,16 @@ Index: ioemu/Makefile.target
  ifndef CONFIG_USER_ONLY
  LIBS+=-lz
  endif
-@@ -281,7 +295,7 @@
+@@ -311,7 +324,7 @@
  all: $(PROGS)
  
  $(QEMU_USER): $(OBJS)
--      $(CC) $(LDFLAGS) -o $@ $^  $(LIBS)
-+      $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^  $(LIBS)
+-      $(CC) $(LDFLAGS) $(BASE_LDFLAGS) -o $@ $^  $(LIBS)
++      $(CC) $(CFLAGS) $(LDFLAGS) $(BASE_LDFLAGS) -o $@ $^  $(LIBS)
  ifeq ($(ARCH),alpha)
  # Mark as 32 bit binary, i. e. it will be mapped into the low 31 bit of
  # the address space (31 bit so sign extending doesn't matter)
-@@ -528,10 +542,16 @@
+@@ -574,10 +587,16 @@
  clean:
        rm -f *.o  *.a *~ $(PROGS) gen-op.h opc.h op.h nwfpe/*.o slirp/*.o fpu/*.o
  
@@ -178,8 +174,8 @@ Index: ioemu/Makefile.target
  include .depend
 Index: ioemu/configure
 ===================================================================
---- ioemu.orig/configure       2007-05-03 15:38:37.000000000 +0100
-+++ ioemu/configure    2007-05-03 15:38:39.000000000 +0100
+--- ioemu.orig/configure       2007-05-09 13:42:55.000000000 +0100
++++ ioemu/configure    2007-05-09 13:42:58.000000000 +0100
 @@ -18,8 +18,8 @@
  
  # default parameters
@@ -189,8 +185,8 @@ Index: ioemu/configure
 +libdir="lib"
  cross_prefix=""
  cc="gcc"
host_cc="gcc"
-@@ -65,6 +65,7 @@
gcc3_search="yes"
+@@ -67,6 +67,7 @@
    ;;
    x86_64|amd64)
      cpu="x86_64"
@@ -198,16 +194,16 @@ Index: ioemu/configure
    ;;
    *)
      cpu="unknown"
-@@ -91,7 +92,7 @@
kernel_path=""
+@@ -92,7 +93,7 @@
profiler="no"
  cocoa="no"
  check_gfx="yes"
 -check_gcc="yes"
 +check_gcc="no"
  softmmu="yes"
- user="no"
build_docs="no"
-@@ -380,6 +381,8 @@
linux_user="no"
darwin_user="no"
+@@ -433,6 +434,8 @@
      exit 1
  fi
  
@@ -216,7 +212,7 @@ Index: ioemu/configure
  if test -z "$cross_prefix" ; then
  
  # ---
-@@ -505,14 +508,16 @@
+@@ -569,14 +572,16 @@
  datadir="$prefix"
  docdir="$prefix"
  bindir="$prefix"
@@ -235,7 +231,7 @@ Index: ioemu/configure
  fi
  
  echo "Install prefix    $prefix"
-@@ -583,6 +588,8 @@
+@@ -647,6 +652,8 @@
  echo "mandir=$mandir" >> $config_mak
  echo "datadir=$datadir" >> $config_mak
  echo "docdir=$docdir" >> $config_mak
@@ -244,7 +240,7 @@ Index: ioemu/configure
  echo "#define CONFIG_QEMU_SHAREDIR \"$datadir\"" >> $config_h
  echo "MAKE=$make" >> $config_mak
  echo "INSTALL=$install" >> $config_mak
-@@ -770,7 +777,7 @@
+@@ -843,7 +850,7 @@
  # don't use ln -sf as not all "ln -sf" over write the file/link
  #
  rm -f $target_dir/Makefile
@@ -253,7 +249,7 @@ Index: ioemu/configure
  
  
  echo "# Automatically generated by configure - do not modify" > $config_mak
-@@ -784,6 +791,12 @@
+@@ -857,6 +864,12 @@
  interp_prefix1=`echo "$interp_prefix" | sed "s/%M/$target_cpu/g"`
  echo "#define CONFIG_QEMU_PREFIX \"$interp_prefix1\"" >> $config_h
  
@@ -266,14 +262,13 @@ Index: ioemu/configure
  if test "$target_cpu" = "i386" ; then
    echo "TARGET_ARCH=i386" >> $config_mak
    echo "#define TARGET_ARCH \"i386\"" >> $config_h
-@@ -850,6 +863,10 @@
-   echo "#define CONFIG_USER_ONLY 1" >> $config_h
+@@ -935,6 +948,9 @@
+   echo "CONFIG_DARWIN_USER=yes" >> $config_mak
+   echo "#define CONFIG_DARWIN_USER 1" >> $config_h
  fi
 +if expr $target : '.*-dm' > /dev/null ; then
 +  echo "#define CONFIG_DM 1" >> $config_h
 +fi
-+
- if test "$target_cpu" = "arm" -o "$target_cpu" = "armeb" -o "$target_cpu" = "sparc" -o "$target_cpu" = "sparc64"; then
+ if test "$target_cpu" = "arm" -o "$target_cpu" = "armeb" -o "$target_cpu" = "sparc" -o "$target_cpu" = "sparc64" -o "$target_cpu" = "m68k"; then
    echo "CONFIG_SOFTFLOAT=yes" >> $config_mak
-   echo "#define CONFIG_SOFTFLOAT 1" >> $config_h
index 36c44d3ec507213383002feff0168a0e3f7971d3..b7ec42ed73ac1e87b7f3f788eeb6eca5b24ff2ce 100644 (file)
@@ -1,8 +1,8 @@
 Index: ioemu/sdl.c
 ===================================================================
---- ioemu.orig/sdl.c   2007-05-02 16:04:45.000000000 +0100
-+++ ioemu/sdl.c        2007-05-02 16:05:51.000000000 +0100
-@@ -273,14 +273,14 @@
+--- ioemu.orig/sdl.c   2007-05-03 18:17:58.000000000 +0100
++++ ioemu/sdl.c        2007-05-03 19:01:57.000000000 +0100
+@@ -213,14 +213,14 @@
  static void sdl_update_caption(void)
  {
      char buf[1024];
@@ -21,26 +21,26 @@ Index: ioemu/sdl.c
  static void sdl_hide_cursor(void)
 Index: ioemu/vl.c
 ===================================================================
---- ioemu.orig/vl.c    2007-05-02 16:05:51.000000000 +0100
-+++ ioemu/vl.c 2007-05-02 16:05:51.000000000 +0100
-@@ -158,6 +158,8 @@
- int acpi_enabled = 1;
- int fd_bootchk = 1;
+--- ioemu.orig/vl.c    2007-05-03 19:00:51.000000000 +0100
++++ ioemu/vl.c 2007-05-03 19:01:57.000000000 +0100
+@@ -175,6 +175,8 @@
+ int semihosting_enabled = 0;
+ int autostart = 1;
  
 +char domain_name[1024] = { 'H','V', 'M', 'X', 'E', 'N', '-'};
 +
  /***********************************************************/
  /* x86 ISA bus support */
  
-@@ -5235,6 +5237,7 @@
+@@ -6128,6 +6130,7 @@
             "-s              wait gdb connection to port %d\n"
             "-p port         change gdb connection port\n"
             "-l item1,...    output log to %s (use -d ? for a list of log items)\n"
 +           "-domain-name    domain name that we're serving\n"
             "-hdachs c,h,s[,t]  force hard disk 0 physical geometry and the optional BIOS\n"
             "                translation (t=none or lba) (usually qemu can guess them)\n"
-            "-L path         set the directory for the BIOS and VGA BIOS\n"
-@@ -5319,6 +5322,7 @@
+            "-L path         set the directory for the BIOS, VGA BIOS and keymaps\n"
+@@ -6217,6 +6220,7 @@
      QEMU_OPTION_g,
      QEMU_OPTION_std_vga,
      QEMU_OPTION_monitor,
@@ -48,7 +48,7 @@ Index: ioemu/vl.c
      QEMU_OPTION_serial,
      QEMU_OPTION_parallel,
      QEMU_OPTION_loadvm,
-@@ -5396,6 +5400,7 @@
+@@ -6300,6 +6304,7 @@
      { "localtime", 0, QEMU_OPTION_localtime },
      { "std-vga", 0, QEMU_OPTION_std_vga },
      { "monitor", 1, QEMU_OPTION_monitor },
@@ -56,9 +56,9 @@ Index: ioemu/vl.c
      { "serial", 1, QEMU_OPTION_serial },
      { "parallel", 1, QEMU_OPTION_parallel },
      { "loadvm", HAS_ARG, QEMU_OPTION_loadvm },
-@@ -6066,6 +6071,9 @@
-             case QEMU_OPTION_no_acpi:
-                 acpi_enabled = 0;
+@@ -7002,6 +7007,9 @@
+             case QEMU_OPTION_semihosting:
+                 semihosting_enabled = 1;
                  break;
 +            case QEMU_OPTION_domainname:
 +                strncat(domain_name, optarg, sizeof(domain_name) - 20);
@@ -68,9 +68,9 @@ Index: ioemu/vl.c
      }
 Index: ioemu/vl.h
 ===================================================================
---- ioemu.orig/vl.h    2007-05-02 16:05:50.000000000 +0100
-+++ ioemu/vl.h 2007-05-02 16:05:51.000000000 +0100
-@@ -1185,4 +1185,5 @@
+--- ioemu.orig/vl.h    2007-05-03 19:00:05.000000000 +0100
++++ ioemu/vl.h 2007-05-03 19:01:57.000000000 +0100
+@@ -1405,4 +1405,5 @@
  
  void kqemu_record_dump(void);
  
index 45bb8f5213328669a057315665047032278b6169..933afb7e7c3dad0ae88ea53796e6f2034679ac63 100644 (file)
@@ -1,16 +1,16 @@
 Index: ioemu/vl.c
 ===================================================================
---- ioemu.orig/vl.c    2007-05-02 16:05:51.000000000 +0100
-+++ ioemu/vl.c 2007-05-02 16:05:51.000000000 +0100
-@@ -159,6 +159,7 @@
- int fd_bootchk = 1;
+--- ioemu.orig/vl.c    2007-05-03 19:01:57.000000000 +0100
++++ ioemu/vl.c 2007-05-03 19:02:49.000000000 +0100
+@@ -176,6 +176,7 @@
+ int autostart = 1;
  
  char domain_name[1024] = { 'H','V', 'M', 'X', 'E', 'N', '-'};
 +extern int domid;
  
  /***********************************************************/
  /* x86 ISA bus support */
-@@ -5237,6 +5238,7 @@
+@@ -6130,6 +6131,7 @@
             "-s              wait gdb connection to port %d\n"
             "-p port         change gdb connection port\n"
             "-l item1,...    output log to %s (use -d ? for a list of log items)\n"
@@ -18,25 +18,25 @@ Index: ioemu/vl.c
             "-domain-name    domain name that we're serving\n"
             "-hdachs c,h,s[,t]  force hard disk 0 physical geometry and the optional BIOS\n"
             "                translation (t=none or lba) (usually qemu can guess them)\n"
-@@ -5336,6 +5338,8 @@
-     QEMU_OPTION_smp,
-     QEMU_OPTION_vnc,
-     QEMU_OPTION_no_acpi,
-+
+@@ -6239,6 +6241,8 @@
+     QEMU_OPTION_daemonize,
+     QEMU_OPTION_option_rom,
+     QEMU_OPTION_semihosting
++    ,
 +    QEMU_OPTION_d,
  };
  
  typedef struct QEMUOption {
-@@ -5415,6 +5419,8 @@
-     { "usb", 0, QEMU_OPTION_usb },
-     { "cirrusvga", 0, QEMU_OPTION_cirrusvga },
-     { "no-acpi", 0, QEMU_OPTION_no_acpi },
+@@ -6328,6 +6332,8 @@
+ #if defined(TARGET_ARM)
+     { "semihosting", 0, QEMU_OPTION_semihosting },
+ #endif
 +    
 +    { "d", HAS_ARG, QEMU_OPTION_d },
      { NULL },
  };
  
-@@ -6074,6 +6080,10 @@
+@@ -7010,6 +7016,10 @@
              case QEMU_OPTION_domainname:
                  strncat(domain_name, optarg, sizeof(domain_name) - 20);
                  break;
index 89a1e0c570d535dc7fba69a914657480e7b307f9..69406283ac4490ab91a748525ef6c63f7bf6f7a9 100644 (file)
@@ -17,18 +17,18 @@ Signed-off-by: Keir Fraser <keir@xensource.com>
 
 Index: ioemu/vl.c
 ===================================================================
---- ioemu.orig/vl.c    2007-05-03 15:12:21.000000000 +0100
-+++ ioemu/vl.c 2007-05-03 15:12:41.000000000 +0100
-@@ -286,7 +286,7 @@
+--- ioemu.orig/vl.c    2007-05-09 13:49:09.000000000 +0100
++++ ioemu/vl.c 2007-05-09 13:49:10.000000000 +0100
+@@ -278,7 +278,7 @@
      for(i = start; i < start + length; i += size) {
-         ioport_write_table[bsize][i] = func;
+         ioport_read_table[bsize][i] = func;
          if (ioport_opaque[i] != NULL && ioport_opaque[i] != opaque)
 -            hw_error("register_ioport_read: invalid opaque");
 +            hw_error("register_ioport_write: invalid opaque");
          ioport_opaque[i] = opaque;
      }
      return 0;
-@@ -5894,6 +5894,157 @@
+@@ -6806,6 +6806,157 @@
      suspend_requested = 1;
  }
  
@@ -186,7 +186,7 @@ Index: ioemu/vl.c
  int main(int argc, char **argv)
  {
  #ifdef CONFIG_GDBSTUB
-@@ -5930,8 +6081,11 @@
+@@ -6842,8 +6993,11 @@
      unsigned long ioreq_pfn;
      extern void *shared_page;
      extern void *buffered_io_page;
@@ -199,7 +199,7 @@ Index: ioemu/vl.c
  
      char qemu_dm_logfilename[64];
  
-@@ -6221,6 +6375,7 @@
+@@ -7136,6 +7290,7 @@
                  break;
              case QEMU_OPTION_m:
                  ram_size = atol(optarg) * 1024 * 1024;
@@ -207,7 +207,7 @@ Index: ioemu/vl.c
                  if (ram_size <= 0)
                      help();
  #ifndef CONFIG_DM
-@@ -6482,30 +6637,15 @@
+@@ -7495,30 +7650,15 @@
  
  #if defined(__i386__) || defined(__x86_64__)
  
@@ -241,7 +241,7 @@ Index: ioemu/vl.c
      if (shared_page == NULL) {
          fprintf(logfile, "map shared IO page returned error %d\n", errno);
          exit(-1);
-@@ -6514,15 +6654,12 @@
+@@ -7527,15 +7667,12 @@
      xc_get_hvm_param(xc_handle, domid, HVM_PARAM_BUFIOREQ_PFN, &ioreq_pfn);
      fprintf(logfile, "buffered io page at pfn %lx\n", ioreq_pfn);
      buffered_io_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
@@ -260,8 +260,8 @@ Index: ioemu/vl.c
      nr_pages = ram_size/PAGE_SIZE;
 Index: ioemu/target-i386-dm/exec-dm.c
 ===================================================================
---- ioemu.orig/target-i386-dm/exec-dm.c        2007-05-03 15:10:22.000000000 +0100
-+++ ioemu/target-i386-dm/exec-dm.c     2007-05-03 15:12:34.000000000 +0100
+--- ioemu.orig/target-i386-dm/exec-dm.c        2007-05-09 13:48:54.000000000 +0100
++++ ioemu/target-i386-dm/exec-dm.c     2007-05-09 13:49:10.000000000 +0100
 @@ -36,6 +36,7 @@
  
  #include "cpu.h"
@@ -380,9 +380,9 @@ Index: ioemu/target-i386-dm/exec-dm.c
  
 Index: ioemu/vl.h
 ===================================================================
---- ioemu.orig/vl.h    2007-05-03 15:12:20.000000000 +0100
-+++ ioemu/vl.h 2007-05-03 15:12:34.000000000 +0100
-@@ -156,6 +156,28 @@
+--- ioemu.orig/vl.h    2007-05-09 13:49:09.000000000 +0100
++++ ioemu/vl.h 2007-05-09 13:49:10.000000000 +0100
+@@ -161,6 +161,28 @@
  
  extern FILE *logfile;
  
@@ -413,8 +413,8 @@ Index: ioemu/vl.h
  
 Index: ioemu/target-i386-dm/cpu.h
 ===================================================================
---- ioemu.orig/target-i386-dm/cpu.h    2007-05-03 15:10:22.000000000 +0100
-+++ ioemu/target-i386-dm/cpu.h 2007-05-03 15:12:21.000000000 +0100
+--- ioemu.orig/target-i386-dm/cpu.h    2007-05-09 13:48:54.000000000 +0100
++++ ioemu/target-i386-dm/cpu.h 2007-05-09 13:49:10.000000000 +0100
 @@ -25,7 +25,8 @@
  #ifdef TARGET_X86_64
  #define TARGET_LONG_BITS 64
@@ -427,8 +427,8 @@ Index: ioemu/target-i386-dm/cpu.h
  /* target supports implicit self modifying code */
 Index: ioemu/target-i386-dm/helper2.c
 ===================================================================
---- ioemu.orig/target-i386-dm/helper2.c        2007-05-03 15:12:19.000000000 +0100
-+++ ioemu/target-i386-dm/helper2.c     2007-05-03 15:12:21.000000000 +0100
+--- ioemu.orig/target-i386-dm/helper2.c        2007-05-09 13:48:54.000000000 +0100
++++ ioemu/target-i386-dm/helper2.c     2007-05-09 13:49:10.000000000 +0100
 @@ -526,6 +526,9 @@
      case IOREQ_TYPE_TIMEOFFSET:
          cpu_ioreq_timeoffset(env, req);
index 37b47c7a8353a0896ed913c85c96d86dfb836119..b1d36608e0017a432ba02f62d3d19e6744cbd563 100644 (file)
@@ -1,8 +1,8 @@
 Index: ioemu/hw/pc.c
 ===================================================================
---- ioemu.orig/hw/pc.c 2007-05-03 09:54:24.000000000 +0100
-+++ ioemu/hw/pc.c      2007-05-03 09:56:32.000000000 +0100
-@@ -646,7 +646,9 @@
+--- ioemu.orig/hw/pc.c 2007-05-03 19:08:13.000000000 +0100
++++ ioemu/hw/pc.c      2007-05-03 19:08:19.000000000 +0100
+@@ -481,7 +481,9 @@
      }
  
      /* allocate RAM */
@@ -12,7 +12,7 @@ Index: ioemu/hw/pc.c
  
      /* BIOS load */
      bios_offset = ram_size + vga_ram_size;
-@@ -678,8 +680,10 @@
+@@ -510,8 +512,10 @@
      ret = load_image(buf, phys_ram_base + vga_bios_offset);
      
      /* setup basic memory access */
@@ -25,36 +25,36 @@ Index: ioemu/hw/pc.c
      isa_bios_size = bios_size;
 Index: ioemu/vl.c
 ===================================================================
---- ioemu.orig/vl.c    2007-05-03 09:54:24.000000000 +0100
-+++ ioemu/vl.c 2007-05-03 10:04:06.000000000 +0100
-@@ -88,6 +88,7 @@
+--- ioemu.orig/vl.c    2007-05-03 19:08:13.000000000 +0100
++++ ioemu/vl.c 2007-05-03 19:08:57.000000000 +0100
+@@ -89,6 +89,7 @@
  
  #include "exec-all.h"
  
 +#include <xen/hvm/params.h>
  #define DEFAULT_NETWORK_SCRIPT "/etc/xen/qemu-ifup"
- //#define DEBUG_UNUSED_IOPORT
-@@ -158,6 +159,8 @@
- int acpi_enabled = 1;
- int fd_bootchk = 1;
+ #ifdef __sun__
+ #define SMBD_COMMAND "/usr/sfw/sbin/smbd"
+@@ -175,6 +176,8 @@
+ int semihosting_enabled = 0;
+ int autostart = 1;
  
 +int xc_handle;
 +
  char domain_name[1024] = { 'H','V', 'M', 'X', 'E', 'N', '-'};
  extern int domid;
  
-@@ -5650,6 +5653,9 @@
-     QEMUMachine *machine;
+@@ -6565,6 +6568,9 @@
      char usb_devices[MAX_USB_CMDLINE][128];
      int usb_devices_index;
+     int fds[2];
 +    unsigned long ioreq_pfn;
 +    extern void *shared_page;
 +    unsigned long nr_pages;
  
      char qemu_dm_logfilename[64];
  
-@@ -5921,11 +5927,13 @@
+@@ -6839,11 +6845,13 @@
                  ram_size = atol(optarg) * 1024 * 1024;
                  if (ram_size <= 0)
                      help();
@@ -68,9 +68,9 @@ Index: ioemu/vl.c
                  break;
              case QEMU_OPTION_l:
                  {
-@@ -6137,12 +6145,53 @@
-     /* init the memory */
-     phys_ram_size = ram_size + vga_ram_size + bios_size;
+@@ -7153,12 +7161,53 @@
+       phys_ram_size += ret;
+     }
  
 +#ifdef CONFIG_DM
 +
@@ -122,23 +122,10 @@ Index: ioemu/vl.c
      /* we always create the cdrom drive, even if no disk is there */
      bdrv_init();
      if (cdrom_index >= 0) {
-Index: ioemu/hw/piix_pci.c
-===================================================================
---- ioemu.orig/hw/piix_pci.c   2007-05-03 09:54:18.000000000 +0100
-+++ ioemu/hw/piix_pci.c        2007-05-03 09:56:32.000000000 +0100
-@@ -399,7 +399,7 @@
-     uint8_t elcr[2];
-     pci_bios_io_addr = 0xc000;
--    pci_bios_mem_addr = 0xf0000000;
-+    pci_bios_mem_addr = HVM_BELOW_4G_MMIO_START;
-     /* activate IRQ mappings */
-     elcr[0] = 0x00;
 Index: ioemu/vl.h
 ===================================================================
---- ioemu.orig/vl.h    2007-05-03 09:54:24.000000000 +0100
-+++ ioemu/vl.h 2007-05-03 09:56:32.000000000 +0100
+--- ioemu.orig/vl.h    2007-05-03 19:08:13.000000000 +0100
++++ ioemu/vl.h 2007-05-03 19:08:19.000000000 +0100
 @@ -39,6 +39,7 @@
  #include <sys/stat.h>
  #include "xenctrl.h"
index 59f627692e99aa80763b32117a077d2273ea061d..8aad7eaaa833597e1c5222ba324d64537b3c8800 100644 (file)
@@ -1,16 +1,16 @@
 Index: ioemu/vl.c
 ===================================================================
---- ioemu.orig/vl.c    2007-05-03 10:07:52.000000000 +0100
-+++ ioemu/vl.c 2007-05-03 10:07:52.000000000 +0100
-@@ -90,6 +90,7 @@
+--- ioemu.orig/vl.c    2007-05-03 19:09:18.000000000 +0100
++++ ioemu/vl.c 2007-05-03 19:11:56.000000000 +0100
+@@ -91,6 +91,7 @@
  
  #include <xen/hvm/params.h>
  #define DEFAULT_NETWORK_SCRIPT "/etc/xen/qemu-ifup"
 +#define DEFAULT_BRIDGE "xenbr0"
- //#define DEBUG_UNUSED_IOPORT
- //#define DEBUG_IOPORT
-@@ -3091,11 +3092,11 @@
+ #ifdef __sun__
+ #define SMBD_COMMAND "/usr/sfw/sbin/smbd"
+ #else
+@@ -3288,11 +3289,11 @@
  #endif
  
  static int net_tap_init(VLANState *vlan, const char *ifname1,
@@ -24,7 +24,7 @@ Index: ioemu/vl.c
      char **parg;
      char ifname[128];
  
-@@ -3114,9 +3115,18 @@
+@@ -3311,9 +3312,18 @@
          pid = fork();
          if (pid >= 0) {
              if (pid == 0) {
@@ -43,7 +43,7 @@ Index: ioemu/vl.c
                  *parg++ = NULL;
                  execv(setup_script, args);
                  _exit(1);
-@@ -3672,6 +3682,7 @@
+@@ -3869,6 +3879,7 @@
      if (!strcmp(device, "tap")) {
          char ifname[64];
          char setup_script[1024];
@@ -51,7 +51,7 @@ Index: ioemu/vl.c
          int fd;
          if (get_param_value(buf, sizeof(buf), "fd", p) > 0) {
              fd = strtol(buf, NULL, 0);
-@@ -3684,7 +3695,10 @@
+@@ -3882,7 +3893,10 @@
              if (get_param_value(setup_script, sizeof(setup_script), "script", p) == 0) {
                  pstrcpy(setup_script, sizeof(setup_script), DEFAULT_NETWORK_SCRIPT);
              }
@@ -63,7 +63,7 @@ Index: ioemu/vl.c
          }
      } else
  #endif
-@@ -5209,7 +5223,7 @@
+@@ -6101,7 +6115,7 @@
             "-net tap[,vlan=n],ifname=name\n"
             "                connect the host TAP network interface to VLAN 'n'\n"
  #else
@@ -71,4 +71,4 @@ Index: ioemu/vl.c
 +           "-net tap[,vlan=n][,fd=h][,ifname=name][,script=file][,bridge=br]\n"
             "                connect the host TAP network interface to VLAN 'n' and use\n"
             "                the network script 'file' (default=%s);\n"
-            "                use 'fd=h' to connect to an already opened TAP interface\n"
+            "                use 'script=no' to disable script execution;\n"
index 995cf5a470ec8776e1acc9a97af8291ec49d7d63..e9700d1df447d57a058b3bd7ed922e1881a80a96 100644 (file)
@@ -3,21 +3,21 @@ will come later.
 
 Index: ioemu/Makefile.target
 ===================================================================
---- ioemu.orig/Makefile.target 2007-05-03 15:16:41.000000000 +0100
-+++ ioemu/Makefile.target      2007-05-03 15:20:35.000000000 +0100
-@@ -360,6 +360,7 @@
- VL_OBJS+= usb-uhci.o
+--- ioemu.orig/Makefile.target 2007-05-09 13:56:21.000000000 +0100
++++ ioemu/Makefile.target      2007-05-09 13:56:35.000000000 +0100
+@@ -391,6 +391,7 @@
+ VL_OBJS+= usb-uhci.o smbus_eeprom.o
  VL_OBJS+= piix4acpi.o
  VL_OBJS+= xenstore.o
 +VL_OBJS+= xen_platform.o
DEFINES += -DHAS_AUDIO
CPPFLAGS += -DHAS_AUDIO
  endif
  ifeq ($(TARGET_BASE_ARCH), ppc)
 Index: ioemu/hw/pc.c
 ===================================================================
---- ioemu.orig/hw/pc.c 2007-05-03 15:18:17.000000000 +0100
-+++ ioemu/hw/pc.c      2007-05-03 15:20:35.000000000 +0100
-@@ -823,6 +823,9 @@
+--- ioemu.orig/hw/pc.c 2007-05-09 13:56:21.000000000 +0100
++++ ioemu/hw/pc.c      2007-05-09 13:56:35.000000000 +0100
+@@ -676,6 +676,9 @@
      }
  #endif /* !CONFIG_DM */
  
@@ -30,8 +30,8 @@ Index: ioemu/hw/pc.c
 Index: ioemu/hw/xen_platform.c
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ ioemu/hw/xen_platform.c    2007-05-03 15:18:17.000000000 +0100
-@@ -0,0 +1,133 @@
++++ ioemu/hw/xen_platform.c    2007-05-09 13:56:47.000000000 +0100
+@@ -0,0 +1,150 @@
 +/*
 + * XEN platform fake pci device, formerly known as the event channel device
 + * 
@@ -131,6 +131,23 @@ Index: ioemu/hw/xen_platform.c
 +    uint8_t  max_lat;
 +};
 +
++void xen_pci_save(QEMUFile *f, void *opaque)
++{
++    PCIDevice *d = opaque;
++
++    pci_device_save(d, f);
++}
++
++int xen_pci_load(QEMUFile *f, void *opaque, int version_id)
++{
++    PCIDevice *d = opaque;
++
++    if (version_id != 1)
++        return -EINVAL;
++
++    return pci_device_load(d, f);
++}
++
 +void pci_xen_platform_init(PCIBus *bus)
 +{
 +    PCIDevice *d;
@@ -162,14 +179,14 @@ Index: ioemu/hw/xen_platform.c
 +    pci_register_io_region(d, 1, 0x1000000, PCI_ADDRESS_SPACE_MEM_PREFETCH,
 +                         platform_mmio_map);
 +
-+    register_savevm("platform", 0, 1, generic_pci_save, generic_pci_load, d);
++    register_savevm("platform", 0, 1, xen_pci_save, xen_pci_load, d);
 +    printf("Done register platform.\n");
 +}
 Index: ioemu/vl.h
 ===================================================================
---- ioemu.orig/vl.h    2007-05-03 15:18:17.000000000 +0100
-+++ ioemu/vl.h 2007-05-03 15:20:39.000000000 +0100
-@@ -1220,6 +1220,10 @@
+--- ioemu.orig/vl.h    2007-05-09 13:56:21.000000000 +0100
++++ ioemu/vl.h 2007-05-09 13:56:35.000000000 +0100
+@@ -1439,6 +1439,10 @@
  extern long time_offset;
  void timeoffset_get(void);
  
index 1289fae1771d4835d3324d6376cdd04632ef42a2..a26cfdbfb4ee7073b714ea0e37bd8bc7e5d0e5e1 100644 (file)
@@ -1,16 +1,16 @@
 Index: ioemu/vl.c
 ===================================================================
---- ioemu.orig/vl.c    2007-05-03 15:09:21.000000000 +0100
-+++ ioemu/vl.c 2007-05-03 15:09:48.000000000 +0100
-@@ -5923,6 +5923,7 @@
-     int usb_devices_index;
+--- ioemu.orig/vl.c    2007-05-09 13:47:16.000000000 +0100
++++ ioemu/vl.c 2007-05-09 13:47:16.000000000 +0100
+@@ -6838,6 +6838,7 @@
+     int fds[2];
      unsigned long ioreq_pfn;
      extern void *shared_page;
 +    extern void *buffered_io_page;
      unsigned long nr_pages;
  
      char qemu_dm_logfilename[64];
-@@ -6499,6 +6500,16 @@
+@@ -7513,6 +7514,16 @@
          exit(-1);
      }
  
@@ -29,8 +29,8 @@ Index: ioemu/vl.c
  #elif defined(__ia64__)
 Index: ioemu/target-i386-dm/helper2.c
 ===================================================================
---- ioemu.orig/target-i386-dm/helper2.c        2007-05-03 15:09:21.000000000 +0100
-+++ ioemu/target-i386-dm/helper2.c     2007-05-03 15:10:03.000000000 +0100
+--- ioemu.orig/target-i386-dm/helper2.c        2007-05-09 13:47:16.000000000 +0100
++++ ioemu/target-i386-dm/helper2.c     2007-05-09 13:47:16.000000000 +0100
 @@ -78,6 +78,10 @@
  
  shared_iopage_t *shared_page = NULL;
@@ -179,4 +179,4 @@ Index: ioemu/target-i386-dm/helper2.c
 +    handle_buffered_io(env);
      main_loop_wait(1); /* For the select() on events */
  
-     /* Stop the IDE thread */
+     /* Save the device state */
index 0bc6b5f0caf3485ff8e945584864402081b284ca..b5cd6c62ec394e4a176253dfafab6b2c62eb37d2 100644 (file)
@@ -1,7 +1,7 @@
 Index: ioemu/xenstore.c
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ ioemu/xenstore.c   2007-05-03 15:17:52.000000000 +0100
++++ ioemu/xenstore.c   2007-05-09 13:47:15.000000000 +0100
 @@ -0,0 +1,139 @@
 +/*
 + * This file is subject to the terms and conditions of the GNU General
@@ -144,9 +144,9 @@ Index: ioemu/xenstore.c
 +}
 Index: ioemu/vl.h
 ===================================================================
---- ioemu.orig/vl.h    2007-05-03 15:15:40.000000000 +0100
-+++ ioemu/vl.h 2007-05-03 15:18:00.000000000 +0100
-@@ -1204,6 +1204,12 @@
+--- ioemu.orig/vl.h    2007-05-09 13:47:15.000000000 +0100
++++ ioemu/vl.h 2007-05-09 13:47:15.000000000 +0100
+@@ -1423,6 +1423,12 @@
  void readline_start(const char *prompt, int is_password,
                      ReadLineFunc *readline_func, void *opaque);
  
@@ -161,23 +161,23 @@ Index: ioemu/vl.h
  extern char domain_name[];
 Index: ioemu/Makefile.target
 ===================================================================
---- ioemu.orig/Makefile.target 2007-05-03 15:15:39.000000000 +0100
-+++ ioemu/Makefile.target      2007-05-03 15:16:41.000000000 +0100
-@@ -359,6 +359,7 @@
+--- ioemu.orig/Makefile.target 2007-05-09 13:44:51.000000000 +0100
++++ ioemu/Makefile.target      2007-05-09 13:47:15.000000000 +0100
+@@ -390,6 +390,7 @@
  VL_OBJS+= cirrus_vga.o mixeng.o parallel.o acpi.o piix_pci.o
- VL_OBJS+= usb-uhci.o
+ VL_OBJS+= usb-uhci.o smbus_eeprom.o
  VL_OBJS+= piix4acpi.o
 +VL_OBJS+= xenstore.o
DEFINES += -DHAS_AUDIO
CPPFLAGS += -DHAS_AUDIO
  endif
  ifeq ($(TARGET_BASE_ARCH), ppc)
 Index: ioemu/vl.c
 ===================================================================
---- ioemu.orig/vl.c    2007-05-03 15:15:40.000000000 +0100
-+++ ioemu/vl.c 2007-05-03 15:17:52.000000000 +0100
-@@ -6371,6 +6371,10 @@
-         }
+--- ioemu.orig/vl.c    2007-05-09 13:47:15.000000000 +0100
++++ ioemu/vl.c 2007-05-09 13:47:15.000000000 +0100
+@@ -7353,6 +7353,10 @@
      }
+ #endif
  
 +#ifdef CONFIG_DM
 +    xenstore_parse_domain_config(domid);
@@ -186,7 +186,7 @@ Index: ioemu/vl.c
  #ifdef USE_KQEMU
      if (smp_cpus > 1)
          kqemu_allowed = 0;
-@@ -6624,6 +6628,8 @@
+@@ -7643,6 +7647,8 @@
          }
      }
  
index 1fd958d5a4fa9be6547a56ef33b6a151f489d852..c127d53887ae94142a5709c9b22af780ba5c6556 100644 (file)
@@ -1,7 +1,7 @@
 Index: ioemu/xenstore.c
 ===================================================================
---- ioemu.orig/xenstore.c      2007-05-03 15:17:52.000000000 +0100
-+++ ioemu/xenstore.c   2007-05-03 15:18:05.000000000 +0100
+--- ioemu.orig/xenstore.c      2007-05-09 13:47:15.000000000 +0100
++++ ioemu/xenstore.c   2007-05-09 13:47:15.000000000 +0100
 @@ -9,8 +9,15 @@
   */
  
@@ -206,9 +206,9 @@ Index: ioemu/xenstore.c
  
 Index: ioemu/vl.c
 ===================================================================
---- ioemu.orig/vl.c    2007-05-03 15:17:52.000000000 +0100
-+++ ioemu/vl.c 2007-05-03 15:18:05.000000000 +0100
-@@ -5331,9 +5331,11 @@
+--- ioemu.orig/vl.c    2007-05-09 13:47:15.000000000 +0100
++++ ioemu/vl.c 2007-05-09 13:47:15.000000000 +0100
+@@ -6220,9 +6220,11 @@
             "Standard options:\n"
             "-M machine      select emulated machine (-M ? for list)\n"
             "-fda/-fdb file  use 'file' as floppy disk 0/1 image\n"
@@ -217,10 +217,10 @@ Index: ioemu/vl.c
             "-hdc/-hdd file  use 'file' as IDE hard disk 2/3 image\n"
             "-cdrom file     use 'file' as IDE cdrom image (cdrom is ide1 master)\n"
 +#endif /* !CONFIG_DM */
-            "-boot [a|c|d]   boot on floppy (a), hard disk (c) or CD-ROM (d)\n"
-          "-snapshot       write to temporary files instead of disk image files\n"
- #ifdef TARGET_I386
-@@ -5460,11 +5462,13 @@
+            "-boot [a|c|d|n] boot on floppy (a), hard disk (c), CD-ROM (d), or network (n)\n"
+            "-snapshot       write to temporary files instead of disk image files\n"
+ #ifdef CONFIG_SDL
+@@ -6358,11 +6360,13 @@
      QEMU_OPTION_M,
      QEMU_OPTION_fda,
      QEMU_OPTION_fdb,
@@ -234,7 +234,7 @@ Index: ioemu/vl.c
      QEMU_OPTION_boot,
      QEMU_OPTION_snapshot,
  #ifdef TARGET_I386
-@@ -5536,11 +5540,13 @@
+@@ -6440,11 +6444,13 @@
      { "M", HAS_ARG, QEMU_OPTION_M },
      { "fda", HAS_ARG, QEMU_OPTION_fda },
      { "fdb", HAS_ARG, QEMU_OPTION_fdb },
@@ -248,7 +248,7 @@ Index: ioemu/vl.c
      { "boot", HAS_ARG, QEMU_OPTION_boot },
      { "snapshot", 0, QEMU_OPTION_snapshot },
  #ifdef TARGET_I386
-@@ -5882,10 +5888,16 @@
+@@ -6797,10 +6803,16 @@
  #ifdef CONFIG_GDBSTUB
      int use_gdbstub, gdbstub_port;
  #endif
@@ -267,7 +267,7 @@ Index: ioemu/vl.c
      const char *kernel_filename, *kernel_cmdline;
      DisplayState *ds = &display_state;
      int cyls, heads, secs, translation;
-@@ -5946,8 +5958,10 @@
+@@ -6861,8 +6873,10 @@
      initrd_filename = NULL;
      for(i = 0; i < MAX_FD; i++)
          fd_filename[i] = NULL;
@@ -278,7 +278,7 @@ Index: ioemu/vl.c
      ram_size = DEFAULT_RAM_SIZE * 1024 * 1024;
      vga_ram_size = VGA_RAM_SIZE;
      bios_size = BIOS_SIZE;
-@@ -5961,11 +5975,13 @@
+@@ -6876,11 +6890,13 @@
      vncunused = 0;
      kernel_filename = NULL;
      kernel_cmdline = "";
@@ -292,7 +292,7 @@ Index: ioemu/vl.c
      cyls = heads = secs = 0;
      translation = BIOS_ATA_TRANSLATION_AUTO;
      pstrcpy(monitor_device, sizeof(monitor_device), "null");
-@@ -6004,7 +6020,11 @@
+@@ -6919,7 +6935,11 @@
              break;
          r = argv[optind];
          if (r[0] != '-') {
@@ -304,7 +304,7 @@ Index: ioemu/vl.c
          } else {
              const QEMUOption *popt;
  
-@@ -6048,6 +6068,7 @@
+@@ -6966,6 +6986,7 @@
              case QEMU_OPTION_initrd:
                  initrd_filename = optarg;
                  break;
@@ -312,7 +312,7 @@ Index: ioemu/vl.c
              case QEMU_OPTION_hda:
              case QEMU_OPTION_hdb:
              case QEMU_OPTION_hdc:
-@@ -6060,6 +6081,7 @@
+@@ -6978,6 +6999,7 @@
                          cdrom_index = -1;
                  }
                  break;
@@ -320,7 +320,7 @@ Index: ioemu/vl.c
              case QEMU_OPTION_snapshot:
                  snapshot = 1;
                  break;
-@@ -6112,11 +6134,13 @@
+@@ -7030,11 +7052,13 @@
              case QEMU_OPTION_append:
                  kernel_cmdline = optarg;
                  break;
@@ -334,23 +334,23 @@ Index: ioemu/vl.c
              case QEMU_OPTION_boot:
                  boot_device = optarg[0];
                  if (boot_device != 'a' && 
-@@ -6372,6 +6396,7 @@
-     }
+@@ -7354,6 +7378,7 @@
+ #endif
  
  #ifdef CONFIG_DM
 +    bdrv_init();
      xenstore_parse_domain_config(domid);
  #endif /* CONFIG_DM */
  
-@@ -6381,6 +6406,7 @@
+@@ -7363,6 +7388,7 @@
  #endif
      linux_boot = (kernel_filename != NULL);
-         
 +#ifndef CONFIG_DM
-     if (!linux_boot && 
+     if (!linux_boot &&
          hd_filename[0] == '\0' && 
          (cdrom_index >= 0 && hd_filename[cdrom_index] == '\0') &&
-@@ -6394,6 +6420,7 @@
+@@ -7376,6 +7402,7 @@
          else
              boot_device = 'd';
      }
@@ -358,7 +358,7 @@ Index: ioemu/vl.c
  
      setvbuf(stdout, NULL, _IOLBF, 0);
      
-@@ -6514,6 +6541,7 @@
+@@ -7528,6 +7555,7 @@
  
  #endif /* !CONFIG_DM */
  
@@ -366,7 +366,7 @@ Index: ioemu/vl.c
      /* we always create the cdrom drive, even if no disk is there */
      bdrv_init();
      if (cdrom_index >= 0) {
-@@ -6540,6 +6568,7 @@
+@@ -7554,6 +7582,7 @@
              }
          }
      }
@@ -376,8 +376,8 @@ Index: ioemu/vl.c
      fd_table[0] = bdrv_new("fda");
 Index: ioemu/monitor.c
 ===================================================================
---- ioemu.orig/monitor.c       2007-05-03 15:17:52.000000000 +0100
-+++ ioemu/monitor.c    2007-05-03 15:18:05.000000000 +0100
+--- ioemu.orig/monitor.c       2007-05-09 13:44:51.000000000 +0100
++++ ioemu/monitor.c    2007-05-09 13:47:15.000000000 +0100
 @@ -24,6 +24,7 @@
  #include "vl.h"
  #include "disas.h"
@@ -386,7 +386,7 @@ Index: ioemu/monitor.c
  
  //#define DEBUG
  //#define DEBUG_COMPLETION
-@@ -330,7 +331,7 @@
+@@ -361,7 +362,7 @@
      return 0;
  }
  
@@ -395,7 +395,7 @@ Index: ioemu/monitor.c
  {
      BlockDriverState *bs;
  
-@@ -342,7 +343,7 @@
+@@ -373,7 +374,7 @@
      eject_device(bs, force);
  }
  
@@ -404,23 +404,11 @@ Index: ioemu/monitor.c
  {
      BlockDriverState *bs;
      int i;
-Index: ioemu/block.c
-===================================================================
---- ioemu.orig/block.c 2007-05-03 15:17:52.000000000 +0100
-+++ ioemu/block.c      2007-05-03 15:18:05.000000000 +0100
-@@ -758,6 +758,7 @@
- static void raw_close(BlockDriverState *bs)
- {
-     BDRVRawState *s = bs->opaque;
-+    bs->total_sectors = 0;
-     close(s->fd);
- }
 Index: ioemu/vl.h
 ===================================================================
---- ioemu.orig/vl.h    2007-05-03 15:18:00.000000000 +0100
-+++ ioemu/vl.h 2007-05-03 15:18:05.000000000 +0100
-@@ -1192,6 +1192,8 @@
+--- ioemu.orig/vl.h    2007-05-09 13:47:15.000000000 +0100
++++ ioemu/vl.h 2007-05-09 13:47:15.000000000 +0100
+@@ -1411,6 +1411,8 @@
  void term_print_help(void);
  void monitor_readline(const char *prompt, int is_password,
                        char *buf, int buf_size);
@@ -429,7 +417,7 @@ Index: ioemu/vl.h
  
  /* readline.c */
  typedef void ReadLineFunc(void *opaque, const char *str);
-@@ -1206,6 +1208,9 @@
+@@ -1425,6 +1427,9 @@
  
  /* xenstore.c */
  void xenstore_parse_domain_config(int domid);
@@ -441,9 +429,9 @@ Index: ioemu/vl.h
  char *xenstore_vm_read(int domid, char *key, int *len);
 Index: ioemu/hw/ide.c
 ===================================================================
---- ioemu.orig/hw/ide.c        2007-05-03 15:17:52.000000000 +0100
-+++ ioemu/hw/ide.c     2007-05-03 15:18:05.000000000 +0100
-@@ -1199,6 +1199,7 @@
+--- ioemu.orig/hw/ide.c        2007-05-09 13:44:51.000000000 +0100
++++ ioemu/hw/ide.c     2007-05-09 13:47:15.000000000 +0100
+@@ -1221,6 +1221,7 @@
          } else {
              ide_atapi_cmd_error(s, SENSE_NOT_READY, 
                                  ASC_MEDIUM_NOT_PRESENT);
@@ -451,3 +439,15 @@ Index: ioemu/hw/ide.c
          }
          break;
      case GPCMD_MODE_SENSE_10:
+Index: ioemu/block-raw.c
+===================================================================
+--- ioemu.orig/block-raw.c     2007-05-09 13:44:51.000000000 +0100
++++ ioemu/block-raw.c  2007-05-09 13:47:15.000000000 +0100
+@@ -383,6 +383,7 @@
+ static void raw_close(BlockDriverState *bs)
+ {
+     BDRVRawState *s = bs->opaque;
++    bs->total_sectors = 0;
+     if (s->fd >= 0) {
+         close(s->fd);
+         s->fd = -1;
index d9664e9bf52055b79ddd6fed9d4f6d24bf958fa9..e271f63383581255bb42213a0c9ff305066fd3af 100644 (file)
@@ -15,8 +15,8 @@ Signed-off-by: Stefan Berger <stefanb@us.ibm.com>
 
 Index: ioemu/xenstore.c
 ===================================================================
---- ioemu.orig/xenstore.c      2007-05-03 15:21:22.000000000 +0100
-+++ ioemu/xenstore.c   2007-05-03 15:22:05.000000000 +0100
+--- ioemu.orig/xenstore.c      2007-05-03 20:38:49.000000000 +0100
++++ ioemu/xenstore.c   2007-05-03 20:38:53.000000000 +0100
 @@ -304,6 +304,143 @@
      return rc;
  }
@@ -163,9 +163,9 @@ Index: ioemu/xenstore.c
      char *buf = NULL, *path = NULL, *value = NULL;
 Index: ioemu/vl.h
 ===================================================================
---- ioemu.orig/vl.h    2007-05-03 15:21:09.000000000 +0100
-+++ ioemu/vl.h 2007-05-03 15:21:47.000000000 +0100
-@@ -1217,6 +1217,24 @@
+--- ioemu.orig/vl.h    2007-05-03 20:38:49.000000000 +0100
++++ ioemu/vl.h 2007-05-03 20:38:53.000000000 +0100
+@@ -1436,6 +1436,24 @@
  void xenstore_write_vncport(int vnc_display);
  int xenstore_read_vncpasswd(int domid);
  
index ded4daa96ade850f874ef0a57409f35b6d8877f0..ef345b5e66f4693a45a48760e0f33388268aba68 100644 (file)
@@ -1,7 +1,7 @@
 Index: ioemu/xenstore.c
 ===================================================================
---- ioemu.orig/xenstore.c      2007-05-03 15:18:05.000000000 +0100
-+++ ioemu/xenstore.c   2007-05-03 15:18:17.000000000 +0100
+--- ioemu.orig/xenstore.c      2007-05-09 13:47:15.000000000 +0100
++++ ioemu/xenstore.c   2007-05-09 13:47:15.000000000 +0100
 @@ -225,6 +225,34 @@
      free(vec);
  }
@@ -39,21 +39,21 @@ Index: ioemu/xenstore.c
      char *buf = NULL, *path = NULL, *value = NULL;
 Index: ioemu/vl.c
 ===================================================================
---- ioemu.orig/vl.c    2007-05-03 15:18:05.000000000 +0100
-+++ ioemu/vl.c 2007-05-03 15:18:17.000000000 +0100
-@@ -6604,6 +6604,7 @@
-       vnc_display = vnc_display_init(ds, vnc_display, vncunused, &vnclisten_addr);
+--- ioemu.orig/vl.c    2007-05-09 13:47:15.000000000 +0100
++++ ioemu/vl.c 2007-05-09 13:47:15.000000000 +0100
+@@ -7621,6 +7621,7 @@
+                                           &vnclisten_addr);
        if (vncviewer)
-           vnc_start_viewer(vnc_display);
-+      xenstore_write_vncport(vnc_display);
+           vnc_start_viewer(vnc_display_port);
++      xenstore_write_vncport(vnc_display_port);
      } else {
  #if defined(CONFIG_SDL)
          sdl_display_init(ds, full_screen);
 Index: ioemu/vl.h
 ===================================================================
---- ioemu.orig/vl.h    2007-05-03 15:18:05.000000000 +0100
-+++ ioemu/vl.h 2007-05-03 15:18:17.000000000 +0100
-@@ -1211,6 +1211,7 @@
+--- ioemu.orig/vl.h    2007-05-09 13:47:15.000000000 +0100
++++ ioemu/vl.h 2007-05-09 13:47:15.000000000 +0100
+@@ -1430,6 +1430,7 @@
  int xenstore_fd(void);
  void xenstore_process_event(void *opaque);
  void xenstore_check_new_media_present(int timeout);
index 0e8ec7ca137eddd847e5a6ac7e85f743e5a242c3..47d7697c1814673152245cd24b4afc5a006f7359 100644 (file)
@@ -1,14 +1,17 @@
-/Makefile/1.1/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/README/1.8/Sun Aug  6 01:03:54 2006//Trelease_0_8_2
-/bios.bin/1.14/Sun Aug  6 01:03:55 2006/-kb/Trelease_0_8_2
-/bios.diff/1.12/Sun Aug  6 01:03:55 2006//Trelease_0_8_2
-/linux_boot.S/1.1/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/linux_boot.bin/1.1/Sun Aug  6 01:03:55 2006/-kb/Trelease_0_8_2
-/ohw.diff/1.2/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
-/openbios-sparc32/1.1/Wed Jun 14 12:36:32 2006/-kb/Trelease_0_8_2
-/ppc_rom.bin/1.6/Sun Aug  6 01:04:00 2006/-kb/Trelease_0_8_2
-/vgabios-cirrus.bin/1.8/Sun Aug  6 01:04:00 2006/-kb/Trelease_0_8_2
-/vgabios.bin/1.8/Sun Aug  6 01:04:00 2006/-kb/Trelease_0_8_2
-/vgabios.diff/1.5/Sun Aug  6 01:04:00 2006//Trelease_0_8_2
-/video.x/1.1/Sun Aug  6 01:04:00 2006/-kb/Trelease_0_8_2
+/Makefile/1.1/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/README/1.9/Thu May  3 17:18:04 2007//Trelease_0_9_0
+/bios.bin/1.19/Thu May  3 17:18:05 2007/-kb/Trelease_0_9_0
+/bios.diff/1.17/Thu May  3 17:18:05 2007//Trelease_0_9_0
+/linux_boot.S/1.1/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/linux_boot.bin/1.1/Thu May  3 17:18:05 2007/-kb/Trelease_0_9_0
+/ohw.diff/1.2/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/openbios-sparc32/1.3/Thu May  3 17:18:06 2007/-kb/Trelease_0_9_0
+/ppc_rom.bin/1.6/Thu May  3 17:18:09 2007/-kb/Trelease_0_9_0
+/pxe-ne2k_pci.bin/1.1/Fri Jan  5 23:48:51 2007//Trelease_0_9_0
+/pxe-pcnet.bin/1.1/Fri Jan  5 23:48:51 2007//Trelease_0_9_0
+/pxe-rtl8139.bin/1.1/Fri Jan  5 23:48:51 2007//Trelease_0_9_0
+/vgabios-cirrus.bin/1.8/Thu May  3 17:18:09 2007/-kb/Trelease_0_9_0
+/vgabios.bin/1.8/Thu May  3 17:18:10 2007/-kb/Trelease_0_9_0
+/vgabios.diff/1.5/Fri Jan  5 14:34:35 2007//Trelease_0_9_0
+/video.x/1.1/Fri Jan  5 14:34:35 2007/-kb/Trelease_0_9_0
 D
index bd48d406fa1b16a1721b34dc4bb6979acc4274da..eed9f4a4fb93e992c8c20b591822041f09711c7e 100644 (file)
@@ -1 +1 @@
-Nrelease_0_8_2
+Nrelease_0_9_0
index fc85eb429179634d9db96458e3252e0a67405dbd..45e4b7cba215e19cae753abc0b58baa894e9ad9f 100644 (file)
@@ -14,3 +14,9 @@
 - OpenBIOS (http://www.openbios.org/) is a free (GPL v2) portable
   firmware implementation. The goal is to implement a 100% IEEE
   1275-1994 (referred to as Open Firmware) compliant firmware.
+
+- The PXE roms come from Rom-o-Matic etherboot 5.4.2.
+  pcnet32:pcnet32 -- [0x1022,0x2000]
+  ns8390:winbond940 -- [0x1050,0x0940]
+  rtl8139:rtl8139 -- [0x10ec,0x8139]
+  http://rom-o-matic.net/
index e87592784a268fe11fa5f88a386bba7c26d9ddeb..86c36c11d179e544f50be365ec17f1ffa506324e 100644 (file)
-Index: apmbios.S
+Index: rombios.h
 ===================================================================
-RCS file: /cvsroot/bochs/bochs/bios/apmbios.S,v
-retrieving revision 1.4
-diff -u -w -r1.4 apmbios.S
---- apmbios.S  26 Dec 2005 10:35:51 -0000      1.4
-+++ apmbios.S  3 May 2006 21:22:46 -0000
-@@ -225,6 +225,7 @@
- APMSYM(05):
-   cmp al, #0x05
-   jne APMSYM(07)
-+  sti
-   hlt
-   jmp APMSYM(ok)
-Index: rombios.c
+RCS file: /cvsroot/bochs/bochs/bios/rombios.h,v
+retrieving revision 1.3
+diff -u -w -r1.3 rombios.h
+--- rombios.h  3 Oct 2006 20:27:30 -0000       1.3
++++ rombios.h  1 Nov 2006 19:16:34 -0000
+@@ -19,7 +19,7 @@
+ //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ /* define it to include QEMU specific code */
+-//#define BX_QEMU
++#define BX_QEMU
+ #ifndef LEGACY
+ #  define BX_ROMBIOS32     1
+Index: rombios32.c
 ===================================================================
-RCS file: /cvsroot/bochs/bochs/bios/rombios.c,v
-retrieving revision 1.160
-diff -u -w -r1.160 rombios.c
---- rombios.c  25 Jan 2006 17:51:49 -0000      1.160
-+++ rombios.c  3 May 2006 21:22:48 -0000
-@@ -1816,6 +1816,7 @@
- {
-   printf(BX_APPNAME" BIOS - build: %s\n%s\nOptions: ",
-     BIOS_BUILD_DATE, bios_cvs_version_string);
-+#if 0
-   printf(
- #ifdef BX_APM
-   "apmbios "
-@@ -1827,6 +1828,9 @@
-   "eltorito "
- #endif
-   "\n\n");
-+#else
-+  printf("apmbios pcibios eltorito \n\n");
+RCS file: /cvsroot/bochs/bochs/bios/rombios32.c,v
+retrieving revision 1.8
+diff -u -w -r1.8 rombios32.c
+--- rombios32.c        3 Oct 2006 20:27:30 -0000       1.8
++++ rombios32.c        1 Nov 2006 19:16:34 -0000
+@@ -852,6 +852,11 @@
+     int ioapic_id, i, len;
+     int mp_config_table_size;
++#ifdef BX_QEMU
++    if (smp_cpus <= 1)
++        return;
 +#endif
- }
- //--------------------------------------------------------------------------
-@@ -3999,6 +4003,29 @@
- }
- #endif
-+
-+void set_e820_range(ES, DI, start, end, type)
-+     Bit16u ES; 
-+     Bit16u DI;
-+     Bit32u start;
-+     Bit32u end; 
-+     Bit16u type;
-+{
-+    write_word(ES, DI, start);
-+    write_word(ES, DI+2, start >> 16);
-+    write_word(ES, DI+4, 0x00);
-+    write_word(ES, DI+6, 0x00);
-+    
-+    end -= start;
-+    write_word(ES, DI+8, end);
-+    write_word(ES, DI+10, end >> 16);
-+    write_word(ES, DI+12, 0x0000);
-+    write_word(ES, DI+14, 0x0000);
-+    
-+    write_word(ES, DI+16, type);
-+    write_word(ES, DI+18, 0x0);
-+}
-+
-   void
- int15_function32(regs, ES, DS, FLAGS)
-   pushad_regs_t regs; // REGS pushed via pushad
-@@ -4063,19 +4090,8 @@
-                 switch(regs.u.r16.bx)
-                 {
-                     case 0:
--                        write_word(ES, regs.u.r16.di, 0x00);
--                        write_word(ES, regs.u.r16.di+2, 0x00);
--                        write_word(ES, regs.u.r16.di+4, 0x00);
--                        write_word(ES, regs.u.r16.di+6, 0x00);
--
--                        write_word(ES, regs.u.r16.di+8, 0xFC00);
--                        write_word(ES, regs.u.r16.di+10, 0x0009);
--                        write_word(ES, regs.u.r16.di+12, 0x0000);
--                        write_word(ES, regs.u.r16.di+14, 0x0000);
--
--                        write_word(ES, regs.u.r16.di+16, 0x1);
--                        write_word(ES, regs.u.r16.di+18, 0x0);
--
-+                        set_e820_range(ES, regs.u.r16.di, 
-+                                       0x0000000L, 0x0009fc00L, 1);
-                         regs.u.r32.ebx = 1;
-                         regs.u.r32.eax = 0x534D4150;
-                         regs.u.r32.ecx = 0x14;
-@@ -4083,6 +4099,24 @@
-                         return;
-                         break;
-                     case 1:
-+                        set_e820_range(ES, regs.u.r16.di, 
-+                                       0x0009fc00L, 0x000a0000L, 2);
-+                        regs.u.r32.ebx = 2;
-+                        regs.u.r32.eax = 0x534D4150;
-+                        regs.u.r32.ecx = 0x14;
-+                        CLEAR_CF();
-+                        return;
-+                        break;
-+                    case 2:
-+                        set_e820_range(ES, regs.u.r16.di, 
-+                                       0x000e8000L, 0x00100000L, 2);
-+                        regs.u.r32.ebx = 3;
-+                        regs.u.r32.eax = 0x534D4150;
-+                        regs.u.r32.ecx = 0x14;
-+                        CLEAR_CF();
-+                        return;
-+                        break;
-+                    case 3:
-                         extended_memory_size = inb_cmos(0x35);
-                         extended_memory_size <<= 8;
-                         extended_memory_size |= inb_cmos(0x34);
-@@ -4092,9 +4126,9 @@
-                             extended_memory_size = 0x3bc000; // everything after this is reserved memory until we get to 0x100000000
-                         }
-                         extended_memory_size *= 1024;
--                        extended_memory_size += 15728640; // make up for the 16mb of memory that is chopped off
-+                        extended_memory_size += (16L * 1024 * 1024);
--                        if(extended_memory_size <= 15728640)
-+                        if(extended_memory_size <= (16L * 1024 * 1024))
-                         {
-                             extended_memory_size = inb_cmos(0x31);
-                             extended_memory_size <<= 8;
-@@ -4102,28 +4136,23 @@
-                             extended_memory_size *= 1024;
-                         }
--                        write_word(ES, regs.u.r16.di, 0x0000);
--                        write_word(ES, regs.u.r16.di+2, 0x0010);
--                        write_word(ES, regs.u.r16.di+4, 0x0000);
--                        write_word(ES, regs.u.r16.di+6, 0x0000);
--
--                        write_word(ES, regs.u.r16.di+8, extended_memory_size);
--                        extended_memory_size >>= 16;
--                        write_word(ES, regs.u.r16.di+10, extended_memory_size);
--                        extended_memory_size >>= 16;
--                        write_word(ES, regs.u.r16.di+12, extended_memory_size);
--                        extended_memory_size >>= 16;
--                        write_word(ES, regs.u.r16.di+14, extended_memory_size);
--
--                        write_word(ES, regs.u.r16.di+16, 0x1);
--                        write_word(ES, regs.u.r16.di+18, 0x0);
--
--                        regs.u.r32.ebx = 0;
-+                        set_e820_range(ES, regs.u.r16.di, 
-+                                       0x00100000L, extended_memory_size, 1);
-+                        regs.u.r32.ebx = 4;
-                         regs.u.r32.eax = 0x534D4150;
-                         regs.u.r32.ecx = 0x14;
-                         CLEAR_CF();
-                         return;
-                         break;
-+                    case 4:
-+                        /* 256KB BIOS area at the end of 4 GB */
-+                        set_e820_range(ES, regs.u.r16.di, 
-+                                       0xfffc0000L, 0x00000000L, 2);
-+                        regs.u.r32.ebx = 0;
-+                        regs.u.r32.eax = 0x534D4150;
-+                        regs.u.r32.ecx = 0x14;
-+                        CLEAR_CF();
-+                        return;
-                     default:  /* AX=E820, DX=534D4150, BX unrecognized */
-                         goto int15_unimplemented;
-                         break;
-@@ -8713,6 +8742,7 @@
-   mov al, #0x80
- bios32_end:
-   popf
-+  and dword ptr[esp+4],0xfffffffc ;; reset CS.RPL for kqemu
-   retf
- .align 16
-@@ -8823,17 +8853,17 @@
- pci_pro_fail:
-   pop edi
-   pop esi
--  sti
-   popf
-   stc
-+  and dword ptr[esp+4],0xfffffffc ;; reset CS.RPL for kqemu
-   retf
- pci_pro_ok:
-   xor ah, ah
-   pop edi
-   pop esi
--  sti
-   popf
-   clc
-+  and dword ptr[esp+4],0xfffffffc ;; reset CS.RPL for kqemu
-   retf
- pci_pro_select_reg:
-@@ -8971,7 +9001,7 @@
-   jmp pci_real_ok
- pci_real_f0d: ;; write configuration dword
-   cmp al, #0x0d
--  jne pci_real_unknown
-+  jne pci_real_f0e
-   call pci_real_select_reg
-   push dx
-   mov dx, #0x0cfc
-@@ -8979,6 +9009,46 @@
-   out dx, eax
-   pop dx
-   jmp pci_real_ok
-+pci_real_f0e: ;; get irq routing options
-+  cmp al, #0x0e
-+  jne pci_real_unknown
-+  SEG ES
-+  cmp word ptr [di], #pci_routing_table_structure_end - pci_routing_table_structure_start
-+  jb pci_real_too_small    
-+  SEG ES
-+  mov word ptr [di], #pci_routing_table_structure_end - pci_routing_table_structure_start        
-+  pushf
-+  push ds
-+  push es
-+  push cx
-+  push si
-+  push di
-+  cld
-+  mov si, #pci_routing_table_structure_start
-+  push cs
-+  pop ds
-+  SEG ES
-+  mov cx, [di+2]
-+  SEG ES
-+  mov es, [di+4]
-+  mov di, cx
-+  mov cx, #pci_routing_table_structure_end - pci_routing_table_structure_start
-+  rep 
-+      movsb
-+  pop di
-+  pop si
-+  pop cx
-+  pop es
-+  pop ds
-+  popf
-+  mov bx, #(1 << 9) | (1 << 11)   ;; irq 9 and 11 are used
-+  jmp pci_real_ok
-+pci_real_too_small:
-+  SEG ES
-+  mov word ptr [di], #pci_routing_table_structure_end - pci_routing_table_structure_start        
-+  mov ah, #0x89
-+  jmp pci_real_fail
 +
- pci_real_unknown:
-   mov ah, #0x81
- pci_real_fail:
-@@ -9019,6 +9089,7 @@
-   dw 0,0 ;; Miniport data
-   db 0,0,0,0,0,0,0,0,0,0,0 ;; reserved
-   db 0x07 ;; checksum
-+pci_routing_table_structure_start:
-   ;; first slot entry PCI-to-ISA (embedded)
-   db 0 ;; pci bus number
-   db 0x08 ;; pci device number (bit 7-3)
-@@ -9097,6 +9168,7 @@
-   dw 0xdef8 ;; IRQ bitmap INTD#
-   db 5 ;; physical slot (0 = embedded)
-   db 0 ;; reserved
-+pci_routing_table_structure_end:
- pci_irq_list:
-   db 11, 10, 9, 5;
+ #ifdef BX_USE_EBDA_TABLES
+     mp_config_table = (uint8_t *)(ram_size - ACPI_DATA_SIZE - MPTABLE_MAX_SIZE);
+ #else
diff --git a/tools/ioemu/pc-bios/pxe-ne2k_pci.bin b/tools/ioemu/pc-bios/pxe-ne2k_pci.bin
new file mode 100644 (file)
index 0000000..8d8fc02
Binary files /dev/null and b/tools/ioemu/pc-bios/pxe-ne2k_pci.bin differ
diff --git a/tools/ioemu/pc-bios/pxe-pcnet.bin b/tools/ioemu/pc-bios/pxe-pcnet.bin
new file mode 100644 (file)
index 0000000..d127d33
Binary files /dev/null and b/tools/ioemu/pc-bios/pxe-pcnet.bin differ
diff --git a/tools/ioemu/pc-bios/pxe-rtl8139.bin b/tools/ioemu/pc-bios/pxe-rtl8139.bin
new file mode 100644 (file)
index 0000000..2b5cacb
Binary files /dev/null and b/tools/ioemu/pc-bios/pxe-rtl8139.bin differ
index 1e49ccfab3b72e7cb6b58f1900ed8dd888f5e7ca..834c778552d5bfcab6fc3a7e6ef7d9f454914cfe 100644 (file)
@@ -1,7 +1,7 @@
 \input texinfo @c -*- texinfo -*-
 @c %**start of header
 @setfilename qemu-doc.info
-@settitle QEMU CPU Emulator User Documentation
+@settitle QEMU Emulator User Documentation
 @exampleindent 0
 @paragraphindent 0
 @c %**end of header
@@ -9,7 +9,7 @@
 @iftex
 @titlepage
 @sp 7
-@center @titlefont{QEMU CPU Emulator}
+@center @titlefont{QEMU Emulator}
 @sp 1
 @center @titlefont{User Documentation}
 @sp 3
@@ -25,7 +25,7 @@
 * Installation::
 * QEMU PC System emulator::
 * QEMU System emulator for non PC targets::
-* QEMU Linux User space emulator::
+* QEMU User space emulator::
 * compilation:: Compilation from the sources
 * Index::
 @end menu
@@ -57,8 +57,8 @@ peripherals. It can be used to launch different Operating Systems
 without rebooting the PC or to debug system code.
 
 @item 
-User mode emulation (Linux host only). In this mode, QEMU can launch
-Linux processes compiled for one CPU on another CPU. It can be used to
+User mode emulation. In this mode, QEMU can launch
+processes compiled for one CPU on another CPU. It can be used to
 launch the Wine Windows API emulator (@url{http://www.winehq.org}) or
 to ease cross-compilation and cross-debugging.
 
@@ -81,7 +81,7 @@ For system emulation, the following hardware targets are supported:
 @item ARM Versatile baseboard (ARM926E)
 @end itemize
 
-For user emulation, x86, PowerPC, ARM, MIPS, and Sparc32/64 CPUs are supported.
+For user emulation, x86, PowerPC, ARM, MIPS, Sparc32/64 and ColdFire(m68k) CPUs are supported.
 
 @node Installation
 @chapter Installation
@@ -206,7 +206,7 @@ Select the emulated machine (@code{-M ?} for list)
 @item -fda file
 @item -fdb file
 Use @var{file} as floppy disk 0/1 image (@pxref{disk_images}). You can
-use the host floppy by using @file{/dev/fd0} as filename.
+use the host floppy by using @file{/dev/fd0} as filename (@pxref{host_drives}).
 
 @item -hda file
 @item -hdb file
@@ -217,16 +217,16 @@ Use @var{file} as hard disk 0, 1, 2 or 3 image (@pxref{disk_images}).
 @item -cdrom file
 Use @var{file} as CD-ROM image (you cannot use @option{-hdc} and and
 @option{-cdrom} at the same time). You can use the host CD-ROM by
-using @file{/dev/cdrom} as filename.
+using @file{/dev/cdrom} as filename (@pxref{host_drives}).
 
-@item -boot [a|c|d]
-Boot on floppy (a), hard disk (c) or CD-ROM (d). Hard disk boot is
-the default.
+@item -boot [a|c|d|n]
+Boot on floppy (a), hard disk (c), CD-ROM (d), or Etherboot (n). Hard disk boot
+is the default.
 
 @item -snapshot
 Write to temporary files instead of disk image files. In this case,
 the raw disk image you use is not written back. You can however force
-the write back by pressing @key{C-a s} (@pxref{disk_images}). 
+the write back by pressing @key{C-a s} (@pxref{disk_images}).
 
 @item -no-fd-bootchk
 Disable boot signature checking for floppy disks in Bochs BIOS. It may
@@ -247,14 +247,21 @@ command line application. The emulated serial port is redirected on
 the console. Therefore, you can still use QEMU to debug a Linux kernel
 with a serial console.
 
-@item -vnc d
+@item -vnc display
 
 Normally, QEMU uses SDL to display the VGA output.  With this option,
-you can have QEMU listen on VNC display @var{d} and redirect the VGA
+you can have QEMU listen on VNC display @var{display} and redirect the VGA
 display over the VNC session.  It is very useful to enable the usb
 tablet device when using this option (option @option{-usbdevice
 tablet}). When using the VNC display, you must use the @option{-k}
-option to set the keyboard layout.
+option to set the keyboard layout if you are not using en-us.
+
+@var{display} may be in the form @var{interface:d}, in which case connections
+will only be allowed from @var{interface} on display @var{d}. Optionally,
+@var{interface} can be omitted.  @var{display} can also be in the form
+@var{unix:path} where @var{path} is the location of a unix socket to listen for
+connections on.
+
 
 @item -k language
 
@@ -302,11 +309,21 @@ Start in full screen.
 Store the QEMU process PID in @var{file}. It is useful if you launch QEMU
 from a script.
 
+@item -daemonize
+Daemonize the QEMU process after initialization.  QEMU will not detach from
+standard IO until it is ready to receive connections on any of its devices.
+This option is a useful way for external programs to launch QEMU without having
+to cope with initialization race conditions.
+
 @item -win2k-hack
 Use it when installing Windows 2000 to avoid a disk full bug. After
 Windows 2000 is installed, you no longer need this option (this option
 slows down the IDE transfers).
 
+@item -option-rom file
+Load the contents of file as an option ROM.  This option is useful to load
+things like EtherBoot.
+
 @end table
 
 USB options:
@@ -341,7 +358,8 @@ hostname reported by the builtin DHCP server.
 @item -net tap[,vlan=n][,fd=h][,ifname=name][,script=file]
 Connect the host TAP network interface @var{name} to VLAN @var{n} and
 use the network script @var{file} to configure it. The default
-network script is @file{/etc/qemu-ifup}. If @var{name} is not
+network script is @file{/etc/qemu-ifup}. Use @option{script=no} to
+disable script execution. If @var{name} is not
 provided, the OS automatically provides one.  @option{fd=h} can be
 used to specify the handle of an already opened host TAP interface. Example:
 
@@ -443,7 +461,7 @@ or @file{C:\WINNT\SYSTEM32\DRIVERS\ETC\LMHOSTS} (Windows NT/2000).
 Then @file{dir} can be accessed in @file{\\smbserver\qemu}.
 
 Note that a SAMBA server must be installed on the host OS in
-@file{/usr/sbin/smbd}. QEMU was tested succesfully with smbd version
+@file{/usr/sbin/smbd}. QEMU was tested successfully with smbd version
 2.2.7a from the Red Hat 9 and version 3.0.10-1.fc3 from Fedora Core 3.
 
 @item -redir [tcp|udp]:host-port:[guest-host]:guest-port
@@ -506,12 +524,16 @@ Redirect the virtual serial port to host character device
 This option can be used several times to simulate up to 4 serials
 ports.
 
+Use @code{-serial none} to disable all serial ports.
+
 Available character devices are:
 @table @code
 @item vc
 Virtual console
 @item pty
 [Linux only] Pseudo TTY (a new PTY is automatically allocated)
+@item none
+No device is allocated.
 @item null
 void device
 @item /dev/XXX
@@ -555,13 +577,14 @@ localhost 5555
 @end table
 
 
-@item tcp:[host]:port[,server][,nowait]
+@item tcp:[host]:port[,server][,nowait][,nodelay]
 The TCP Net Console has two modes of operation.  It can send the serial
 I/O to a location or wait for a connection from a location.  By default
 the TCP Net Console is sent to @var{host} at the @var{port}.  If you use
-the @var{,server} option QEMU will wait for a client socket application
-to connect to the port before continuing, unless the @code{,nowait}
-option was specified. If @var{host} is omitted, 0.0.0.0 is assumed. Only
+the @var{server} option QEMU will wait for a client socket application
+to connect to the port before continuing, unless the @code{nowait}
+option was specified.  The @code{nodelay} option disables the Nagle buffering
+algoritm.  If @var{host} is omitted, 0.0.0.0 is assumed. Only
 one TCP connection at a time is accepted. You can use @code{telnet} to
 connect to the corresponding character device.
 @table @code
@@ -573,7 +596,7 @@ connect to the corresponding character device.
 -serial tcp:192.168.0.100:4444,server,nowait
 @end table
 
-@item telnet:host:port[,server][,nowait]
+@item telnet:host:port[,server][,nowait][,nodelay]
 The telnet protocol is used instead of raw tcp sockets.  The options
 work the same as if you had specified @code{-serial tcp}.  The
 difference is that the port acts like a telnet server or client using
@@ -582,6 +605,11 @@ MAGIC_SYSRQ sequence if you use a telnet that supports sending the break
 sequence.  Typically in unix telnet you do it with Control-] and then
 type "send break" followed by pressing the enter key.
 
+@item unix:path[,server][,nowait]
+A unix domain socket is used instead of a tcp socket.  The option works the
+same as if you had specified @code{-serial tcp} except the unix domain socket
+@var{path} is used for connections.
+
 @end table
 
 @item -parallel dev
@@ -593,6 +621,8 @@ parallel port.
 This option can be used several times to simulate up to 3 parallel
 ports.
 
+Use @code{-parallel none} to disable all parallel ports.
+
 @item -monitor dev
 Redirect the monitor to host device @var{dev} (same devices as the
 serial port).
@@ -602,7 +632,8 @@ non graphical mode.
 @item -s
 Wait gdb connection to port 1234 (@pxref{gdb_usage}). 
 @item -p port
-Change gdb connection port.
+Change gdb connection port.  @var{port} can be either a decimal number
+to specify a TCP port, or a host device (same devices as the serial port).
 @item -S
 Do not start CPU at startup (you must type 'c' in the monitor).
 @item -d             
@@ -614,6 +645,9 @@ translation mode (@var{t}=none, lba or auto). Usually QEMU can guess
 all thoses parameters. This option is useful for old MS-DOS disk
 images.
 
+@item -L path
+Set the directory for the BIOS, VGA BIOS and keymaps.
+
 @item -std-vga
 Simulate a standard VGA card with Bochs VBE extensions (default is
 Cirrus Logic GD5446 PCI VGA). If your guest OS supports the VESA 2.0
@@ -625,8 +659,16 @@ Disable ACPI (Advanced Configuration and Power Interface) support. Use
 it if your guest OS complains about ACPI problems (PC target machine
 only).
 
+@item -no-reboot
+Exit instead of rebooting.
+
 @item -loadvm file
 Start right away with a saved state (@code{loadvm} in monitor)
+
+@item -semihosting
+Enable "Angel" semihosting interface (ARM target machines only).
+Note that this allows guest direct access to the host filesystem,
+so should only be used with trusted guest OS.
 @end table
 
 @c man end
@@ -666,7 +708,7 @@ During emulation, if you are using the @option{-nographic} option, use
 @item Ctrl-a h
 Print this help
 @item Ctrl-a x    
-Exit emulatior
+Exit emulator
 @item Ctrl-a s    
 Save disk data back to file (if -snapshot)
 @item Ctrl-a b
@@ -743,6 +785,10 @@ show USB devices plugged on the virtual USB hub
 show all USB host devices
 @item info capture
 show information about active capturing
+@item info snapshots
+show list of VM snapshots
+@item info mice
+show which guest mouse is receiving events
 @end table
 
 @item q or quit
@@ -757,6 +803,20 @@ Change a removable media.
 @item screendump filename
 Save screen into PPM image @var{filename}.
 
+@item mouse_move dx dy [dz]
+Move the active mouse to the specified coordinates @var{dx} @var{dy}
+with optional scroll axis @var{dz}.
+
+@item mouse_button val
+Change the active mouse button state @var{val} (1=L, 2=M, 4=R).
+
+@item mouse_set index
+Set which mouse device receives events at given @var{index}, index
+can be obtained with
+@example
+info mice
+@end example
+
 @item wavcapture filename [frequency [bits [channels]]]
 Capture audio into @var{filename}. Using sample rate @var{frequency}
 bits per sample @var{bits} and number of channels @var{channels}.
@@ -777,11 +837,18 @@ info capture
 @item log item1[,...]
 Activate logging of the specified items to @file{/tmp/qemu.log}.
 
-@item savevm filename
-Save the whole virtual machine state to @var{filename}.
+@item savevm [tag|id]
+Create a snapshot of the whole virtual machine. If @var{tag} is
+provided, it is used as human readable identifier. If there is already
+a snapshot with the same tag or ID, it is replaced. More info at
+@ref{vm_snapshots}.
 
-@item loadvm filename
-Restore the whole virtual machine state from @var{filename}.
+@item loadvm tag|id
+Set the whole virtual machine to the snapshot identified by the tag
+@var{tag} or the unique snapshot ID @var{id}.
+
+@item delvm tag|id
+Delete the snapshot identified by @var{tag} or @var{id}.
 
 @item stop
 Stop emulation.
@@ -895,12 +962,16 @@ CPU registers by prefixing them with @emph{$}.
 
 Since version 0.6.1, QEMU supports many disk image formats, including
 growable disk images (their size increase as non empty sectors are
-written), compressed and encrypted disk images.
+written), compressed and encrypted disk images. Version 0.8.3 added
+the new qcow2 disk image format which is essential to support VM
+snapshots.
 
 @menu
 * disk_images_quickstart::    Quick start for disk image creation
 * disk_images_snapshot_mode:: Snapshot mode
+* vm_snapshots::              VM snapshots
 * qemu_img_invocation::       qemu-img Invocation
+* host_drives::               Using host drives
 * disk_images_fat_images::    Virtual FAT disk images
 @end menu
 
@@ -926,11 +997,124 @@ a temporary file created in @file{/tmp}. You can however force the
 write back to the raw disk images by using the @code{commit} monitor
 command (or @key{C-a s} in the serial console).
 
+@node vm_snapshots
+@subsection VM snapshots
+
+VM snapshots are snapshots of the complete virtual machine including
+CPU state, RAM, device state and the content of all the writable
+disks. In order to use VM snapshots, you must have at least one non
+removable and writable block device using the @code{qcow2} disk image
+format. Normally this device is the first virtual hard drive.
+
+Use the monitor command @code{savevm} to create a new VM snapshot or
+replace an existing one. A human readable name can be assigned to each
+snapshot in addition to its numerical ID.
+
+Use @code{loadvm} to restore a VM snapshot and @code{delvm} to remove
+a VM snapshot. @code{info snapshots} lists the available snapshots
+with their associated information:
+
+@example
+(qemu) info snapshots
+Snapshot devices: hda
+Snapshot list (from hda):
+ID        TAG                 VM SIZE                DATE       VM CLOCK
+1         start                   41M 2006-08-06 12:38:02   00:00:14.954
+2                                 40M 2006-08-06 12:43:29   00:00:18.633
+3         msys                    40M 2006-08-06 12:44:04   00:00:23.514
+@end example
+
+A VM snapshot is made of a VM state info (its size is shown in
+@code{info snapshots}) and a snapshot of every writable disk image.
+The VM state info is stored in the first @code{qcow2} non removable
+and writable block device. The disk image snapshots are stored in
+every disk image. The size of a snapshot in a disk image is difficult
+to evaluate and is not shown by @code{info snapshots} because the
+associated disk sectors are shared among all the snapshots to save
+disk space (otherwise each snapshot would need a full copy of all the
+disk images).
+
+When using the (unrelated) @code{-snapshot} option
+(@ref{disk_images_snapshot_mode}), you can always make VM snapshots,
+but they are deleted as soon as you exit QEMU.
+
+VM snapshots currently have the following known limitations:
+@itemize
+@item 
+They cannot cope with removable devices if they are removed or
+inserted after a snapshot is done.
+@item 
+A few device drivers still have incomplete snapshot support so their
+state is not saved or restored properly (in particular USB).
+@end itemize
+
 @node qemu_img_invocation
 @subsection @code{qemu-img} Invocation
 
 @include qemu-img.texi
 
+@node host_drives
+@subsection Using host drives
+
+In addition to disk image files, QEMU can directly access host
+devices. We describe here the usage for QEMU version >= 0.8.3.
+
+@subsubsection Linux
+
+On Linux, you can directly use the host device filename instead of a
+disk image filename provided you have enough proviledge to access
+it. For example, use @file{/dev/cdrom} to access to the CDROM or
+@file{/dev/fd0} for the floppy.
+
+@table @code
+@item CD
+You can specify a CDROM device even if no CDROM is loaded. QEMU has
+specific code to detect CDROM insertion or removal. CDROM ejection by
+the guest OS is supported. Currently only data CDs are supported.
+@item Floppy
+You can specify a floppy device even if no floppy is loaded. Floppy
+removal is currently not detected accurately (if you change floppy
+without doing floppy access while the floppy is not loaded, the guest
+OS will think that the same floppy is loaded).
+@item Hard disks
+Hard disks can be used. Normally you must specify the whole disk
+(@file{/dev/hdb} instead of @file{/dev/hdb1}) so that the guest OS can
+see it as a partitioned disk. WARNING: unless you know what you do, it
+is better to only make READ-ONLY accesses to the hard disk otherwise
+you may corrupt your host data (use the @option{-snapshot} command
+line option or modify the device permissions accordingly).
+@end table
+
+@subsubsection Windows
+
+@table @code
+@item CD
+The prefered syntax is the drive letter (e.g. @file{d:}). The
+alternate syntax @file{\\.\d:} is supported. @file{/dev/cdrom} is
+supported as an alias to the first CDROM drive.
+
+Currently there is no specific code to handle removable medias, so it
+is better to use the @code{change} or @code{eject} monitor commands to
+change or eject media.
+@item Hard disks
+Hard disks can be used with the syntax: @file{\\.\PhysicalDriveN}
+where @var{N} is the drive number (0 is the first hard disk).
+
+WARNING: unless you know what you do, it is better to only make
+READ-ONLY accesses to the hard disk otherwise you may corrupt your
+host data (use the @option{-snapshot} command line so that the
+modifications are written in a temporary file).
+@end table
+
+
+@subsubsection Mac OS X
+
+@file{/dev/cdrom} is an alias to the first CDROM. 
+
+Currently there is no specific code to handle removable medias, so it
+is better to use the @code{change} or @code{eject} monitor commands to
+change or eject media.
+
 @node disk_images_fat_images
 @subsection Virtual FAT disk images
 
@@ -990,6 +1174,8 @@ This is the standard way to connect QEMU to a real network. QEMU adds
 a virtual network device on your host (called @code{tapN}), and you
 can then configure it as if it was a real ethernet card.
 
+@subsubsection Linux host
+
 As an example, you can download the @file{linux-test-xxx.tar.gz}
 archive and copy the script @file{qemu-ifup} in @file{/etc} and
 configure properly @code{sudo} so that the command @code{ifconfig}
@@ -997,9 +1183,15 @@ contained in @file{qemu-ifup} can be executed as root. You must verify
 that your host kernel supports the TAP network interfaces: the
 device @file{/dev/net/tun} must be present.
 
-See @ref{direct_linux_boot} to have an example of network use with a
-Linux distribution and @ref{sec_invocation} to have examples of
-command lines using the TAP network interfaces.
+See @ref{sec_invocation} to have examples of command lines using the
+TAP network interfaces.
+
+@subsubsection Windows host
+
+There is a virtual ethernet driver for Windows 2000/XP systems, called
+TAP-Win32. But it is not included in standard QEMU for Windows,
+so you will need to get it separately. It is part of OpenVPN package,
+so download OpenVPN from : @url{http://openvpn.net/}.
 
 @subsection Using the user mode network stack
 
@@ -1049,146 +1241,31 @@ basic example.
 
 This section explains how to launch a Linux kernel inside QEMU without
 having to make a full bootable image. It is very useful for fast Linux
-kernel testing. The QEMU network configuration is also explained.
-
-@enumerate
-@item
-Download the archive @file{linux-test-xxx.tar.gz} containing a Linux
-kernel and a disk image. 
-
-@item Optional: If you want network support (for example to launch X11 examples), you
-must copy the script @file{qemu-ifup} in @file{/etc} and configure
-properly @code{sudo} so that the command @code{ifconfig} contained in
-@file{qemu-ifup} can be executed as root. You must verify that your host
-kernel supports the TUN/TAP network interfaces: the device
-@file{/dev/net/tun} must be present.
-
-When network is enabled, there is a virtual network connection between
-the host kernel and the emulated kernel. The emulated kernel is seen
-from the host kernel at IP address 172.20.0.2 and the host kernel is
-seen from the emulated kernel at IP address 172.20.0.1.
-
-@item Launch @code{qemu.sh}. You should have the following output:
-
-@smallexample
-> ./qemu.sh 
-Connected to host network interface: tun0
-Linux version 2.4.21 (bellard@@voyager.localdomain) (gcc version 3.2.2 20030222 @/(Red Hat @/Linux 3.2.2-5)) #5 Tue Nov 11 18:18:53 CET 2003
-BIOS-provided physical RAM map:
- BIOS-e801: 0000000000000000 - 000000000009f000 (usable)
- BIOS-e801: 0000000000100000 - 0000000002000000 (usable)
-32MB LOWMEM available.
-On node 0 totalpages: 8192
-zone(0): 4096 pages.
-zone(1): 4096 pages.
-zone(2): 0 pages.
-Kernel command line: root=/dev/hda sb=0x220,5,1,5 ide2=noprobe ide3=noprobe ide4=noprobe @/ide5=noprobe console=ttyS0
-ide_setup: ide2=noprobe
-ide_setup: ide3=noprobe
-ide_setup: ide4=noprobe
-ide_setup: ide5=noprobe
-Initializing CPU#0
-Detected 2399.621 MHz processor.
-Console: colour EGA 80x25
-Calibrating delay loop... 4744.80 BogoMIPS
-Memory: 28872k/32768k available (1210k kernel code, 3508k reserved, 266k data, 64k init, @/0k highmem)
-Dentry cache hash table entries: 4096 (order: 3, 32768 bytes)
-Inode cache hash table entries: 2048 (order: 2, 16384 bytes)
-Mount cache hash table entries: 512 (order: 0, 4096 bytes)
-Buffer-cache hash table entries: 1024 (order: 0, 4096 bytes)
-Page-cache hash table entries: 8192 (order: 3, 32768 bytes)
-CPU: Intel Pentium Pro stepping 03
-Checking 'hlt' instruction... OK.
-POSIX conformance testing by UNIFIX
-Linux NET4.0 for Linux 2.4
-Based upon Swansea University Computer Society NET3.039
-Initializing RT netlink socket
-apm: BIOS not found.
-Starting kswapd
-Journalled Block Device driver loaded
-Detected PS/2 Mouse Port.
-pty: 256 Unix98 ptys configured
-Serial driver version 5.05c (2001-07-08) with no serial options enabled
-ttyS00 at 0x03f8 (irq = 4) is a 16450
-ne.c:v1.10 9/23/94 Donald Becker (becker@@scyld.com)
-Last modified Nov 1, 2000 by Paul Gortmaker
-NE*000 ethercard probe at 0x300: 52 54 00 12 34 56
-eth0: NE2000 found at 0x300, using IRQ 9.
-RAMDISK driver initialized: 16 RAM disks of 4096K size 1024 blocksize
-Uniform Multi-Platform E-IDE driver Revision: 7.00beta4-2.4
-ide: Assuming 50MHz system bus speed for PIO modes; override with idebus=xx
-hda: QEMU HARDDISK, ATA DISK drive
-ide0 at 0x1f0-0x1f7,0x3f6 on irq 14
-hda: attached ide-disk driver.
-hda: 20480 sectors (10 MB) w/256KiB Cache, CHS=20/16/63
-Partition check:
- hda:
-Soundblaster audio driver Copyright (C) by Hannu Savolainen 1993-1996
-NET4: Linux TCP/IP 1.0 for NET4.0
-IP Protocols: ICMP, UDP, TCP, IGMP
-IP: routing cache hash table of 512 buckets, 4Kbytes
-TCP: Hash tables configured (established 2048 bind 4096)
-NET4: Unix domain sockets 1.0/SMP for Linux NET4.0.
-EXT2-fs warning: mounting unchecked fs, running e2fsck is recommended
-VFS: Mounted root (ext2 filesystem).
-Freeing unused kernel memory: 64k freed
-Linux version 2.4.21 (bellard@@voyager.localdomain) (gcc version 3.2.2 20030222 @/(Red Hat @/Linux 3.2.2-5)) #5 Tue Nov 11 18:18:53 CET 2003
-QEMU Linux test distribution (based on Redhat 9)
-Type 'exit' to halt the system
-sh-2.05b# 
-@end smallexample
-
-@item
-Then you can play with the kernel inside the virtual serial console. You
-can launch @code{ls} for example. Type @key{Ctrl-a h} to have an help
-about the keys you can type inside the virtual serial console. In
-particular, use @key{Ctrl-a x} to exit QEMU and use @key{Ctrl-a b} as
-the Magic SysRq key.
-
-@item 
-If the network is enabled, launch the script @file{/etc/linuxrc} in the
-emulator (don't forget the leading dot):
-@example
-. /etc/linuxrc
-@end example
+kernel testing.
 
-Then enable X11 connections on your PC from the emulated Linux: 
+The syntax is:
 @example
-xhost +172.20.0.2
+qemu -kernel arch/i386/boot/bzImage -hda root-2.4.20.img -append "root=/dev/hda"
 @end example
 
-You can now launch @file{xterm} or @file{xlogo} and verify that you have
-a real Virtual Linux system !
+Use @option{-kernel} to provide the Linux kernel image and
+@option{-append} to give the kernel command line arguments. The
+@option{-initrd} option can be used to provide an INITRD image.
 
-@end enumerate
-
-NOTES:
-@enumerate
-@item 
-A 2.5.74 kernel is also included in the archive. Just
-replace the bzImage in qemu.sh to try it.
-
-@item 
-In order to exit cleanly from qemu, you can do a @emph{shutdown} inside
-qemu. qemu will automatically exit when the Linux shutdown is done.
+When using the direct Linux boot, a disk image for the first hard disk
+@file{hda} is required because its boot sector is used to launch the
+Linux kernel.
 
-@item 
-You can boot slightly faster by disabling the probe of non present IDE
-interfaces. To do so, add the following options on the kernel command
-line:
+If you do not need graphical output, you can disable it and redirect
+the virtual serial port and the QEMU monitor to the console with the
+@option{-nographic} option. The typical command line is:
 @example
-ide1=noprobe ide2=noprobe ide3=noprobe ide4=noprobe ide5=noprobe
+qemu -kernel arch/i386/boot/bzImage -hda root-2.4.20.img \
+     -append "root=/dev/hda console=ttyS0" -nographic
 @end example
 
-@item 
-The example disk image is a modified version of the one made by Kevin
-Lawton for the plex86 Project (@url{www.plex86.org}).
-
-@end enumerate
+Use @key{Ctrl-a c} to switch between the serial console and the
+monitor (@pxref{pcsys_keys}).
 
 @node pcsys_usb
 @section USB emulation
@@ -1196,7 +1273,7 @@ Lawton for the plex86 Project (@url{www.plex86.org}).
 QEMU emulates a PCI UHCI USB controller. You can virtually plug
 virtual USB devices or real host USB devices (experimental, works only
 on Linux hosts).  Qemu will automatically create and connect virtual USB hubs
-as neccessary to connect multiple USB devices.
+as necessary to connect multiple USB devices.
 
 @menu
 * usb_devices::
@@ -1212,7 +1289,7 @@ or the @code{usb_add} monitor command.  Available devices are:
 @item @code{mouse}
 Virtual Mouse.  This will override the PS/2 mouse emulation when activated.
 @item @code{tablet}
-Pointer device that uses abolsute coordinates (like a touchscreen).
+Pointer device that uses absolute coordinates (like a touchscreen).
 This means qemu is able to report the mouse position without having
 to grab the mouse.  Also overrides the PS/2 mouse emulation when activated.
 @item @code{disk:file}
@@ -1385,7 +1462,7 @@ correctly instructs QEMU to shutdown at the appropriate moment.
 
 See @ref{sec_invocation} about the help of the option @option{-smb}.
 
-@subsubsection Windows XP security problems
+@subsubsection Windows XP security problem
 
 Some releases of Windows XP install correctly but give a security
 error when booting:
@@ -1393,10 +1470,12 @@ error when booting:
 A problem is preventing Windows from accurately checking the
 license for this computer. Error code: 0x800703e6.
 @end example
-The only known workaround is to boot in Safe mode
-without networking support. 
 
-Future QEMU releases are likely to correct this bug.
+The workaround is to install a service pack for XP after a boot in safe
+mode. Then reboot, and the problem should go away. Since there is no
+network while in safe mode, its recommended to download the full
+installation of SP1 or SP2 and transfer that via an ISO or using the
+vvfat block device ("-hdb fat:directory_which_holds_the_SP").
 
 @subsection MS-DOS and FreeDOS
 
@@ -1625,8 +1704,29 @@ LSI53C895A PCI SCSI Host Bus Adapter with hard disk and CD-ROM devices.
 A Linux 2.6 test image is available on the QEMU web site. More
 information is available in the QEMU mailing-list archive.
 
-@node QEMU Linux User space emulator 
-@chapter QEMU Linux User space emulator 
+@node QEMU User space emulator 
+@chapter QEMU User space emulator 
+
+@menu
+* Supported Operating Systems ::
+* Linux User space emulator::
+* Mac OS X/Darwin User space emulator ::
+@end menu
+
+@node Supported Operating Systems
+@section Supported Operating Systems
+
+The following OS are supported in user space emulation:
+
+@itemize @minus
+@item
+Linux (refered as qemu-linux-user)
+@item
+Mac OS X/Darwin (refered as qemu-darwin-user)
+@end itemize
+
+@node Linux User space emulator
+@section Linux User space emulator
 
 @menu
 * Quick Start::
@@ -1636,7 +1736,7 @@ information is available in the QEMU mailing-list archive.
 @end menu
 
 @node Quick Start
-@section Quick Start
+@subsection Quick Start
 
 In order to launch a Linux process, QEMU needs the process executable
 itself and all the target (x86) dynamic libraries used by it. 
@@ -1686,7 +1786,7 @@ qemu-i386 /usr/local/qemu-i386/bin/qemu-i386 \
 @end itemize
 
 @node Wine launch
-@section Wine launch
+@subsection Wine launch
 
 @itemize
 
@@ -1715,7 +1815,7 @@ qemu-i386 /usr/local/qemu-i386/wine/bin/wine \
 @end itemize
 
 @node Command line options
-@section Command line options
+@subsection Command line options
 
 @example
 usage: qemu-i386 [-h] [-d] [-L path] [-s size] program [arguments...]
@@ -1740,14 +1840,103 @@ Act as if the host page size was 'pagesize' bytes
 @end table
 
 @node Other binaries
-@section Other binaries
+@subsection Other binaries
 
 @command{qemu-arm} is also capable of running ARM "Angel" semihosted ELF
 binaries (as implemented by the arm-elf and arm-eabi Newlib/GDB
 configurations), and arm-uclinux bFLT format binaries.
 
+@command{qemu-m68k} is capable of running semihosted binaries using the BDM
+(m5xxx-ram-hosted.ld) or m68k-sim (sim.ld) syscall interfaces, and
+coldfire uClinux bFLT format binaries.
+
 The binary format is detected automatically.
 
+@node Mac OS X/Darwin User space emulator
+@section Mac OS X/Darwin User space emulator
+
+@menu
+* Mac OS X/Darwin Status::
+* Mac OS X/Darwin Quick Start::
+* Mac OS X/Darwin Command line options::
+@end menu
+
+@node Mac OS X/Darwin Status
+@subsection Mac OS X/Darwin Status
+
+@itemize @minus
+@item
+target x86 on x86: Most apps (Cocoa and Carbon too) works. [1]
+@item
+target PowerPC on x86: Not working as the ppc commpage can't be mapped (yet!)
+@item
+target x86 on x86: Most apps (Cocoa and Carbon too) works. [1]
+@item
+target x86 on PowerPC: most utilities work. Cocoa and Carbon apps are not yet supported.
+@end itemize
+
+[1] If you're host commpage can be executed by qemu.
+
+@node Mac OS X/Darwin Quick Start
+@subsection Quick Start
+
+In order to launch a Mac OS X/Darwin process, QEMU needs the process executable
+itself and all the target dynamic libraries used by it. If you don't have the FAT
+libraries (you're running Mac OS X/ppc) you'll need to obtain it from a Mac OS X
+CD or compile them by hand.
+
+@itemize
+
+@item On x86, you can just try to launch any process by using the native
+libraries:
+
+@example 
+qemu-darwin-i386 /bin/ls
+@end example
+
+or to run the ppc version of the executable:
+
+@example 
+qemu-darwin-ppc /bin/ls
+@end example
+
+@item On ppc, you'll have to tell qemu where your x86 libraries (and dynamic linker)
+are installed:
+
+@example 
+qemu-darwin-i386 -L /opt/x86_root/ /bin/ls
+@end example
+
+@code{-L /opt/x86_root/} tells that the dynamic linker (dyld) path is in
+@file{/opt/x86_root/usr/bin/dyld}.
+
+@end itemize
+
+@node Mac OS X/Darwin Command line options
+@subsection Command line options
+
+@example
+usage: qemu-darwin-i386 [-h] [-d] [-L path] [-s size] program [arguments...]
+@end example
+
+@table @option
+@item -h
+Print the help
+@item -L path   
+Set the library root path (default=/)
+@item -s size
+Set the stack size in bytes (default=524288)
+@end table
+
+Debug options:
+
+@table @option
+@item -d
+Activate log (logfile=/tmp/qemu.log)
+@item -p pagesize
+Act as if the host page size was 'pagesize' bytes
+@end table
+
 @node compilation
 @chapter Compilation from the sources
 
@@ -1782,39 +1971,15 @@ make install
 @end example
 to install QEMU in @file{/usr/local}.
 
-@subsection Tested tool versions
+@subsection GCC version
 
-In order to compile QEMU succesfully, it is very important that you
-have the right tools. The most important one is gcc. I cannot guaranty
-that QEMU works if you do not use a tested gcc version. Look at
-'configure' and 'Makefile' if you want to make a different gcc
-version work.
-
-@example
-host      gcc      binutils      glibc    linux       distribution
-----------------------------------------------------------------------
-x86       3.2      2.13.2        2.1.3    2.4.18
-          2.96     2.11.93.0.2   2.2.5    2.4.18      Red Hat 7.3
-          3.2.2    2.13.90.0.18  2.3.2    2.4.20      Red Hat 9
-
-PowerPC   3.3 [4]  2.13.90.0.18  2.3.1    2.4.20briq
-          3.2
-
-Alpha     3.3 [1]  2.14.90.0.4   2.2.5    2.2.20 [2]  Debian 3.0
-
-Sparc32   2.95.4   2.12.90.0.1   2.2.5    2.4.18      Debian 3.0
-
-ARM       2.95.4   2.12.90.0.1   2.2.5    2.4.9 [3]   Debian 3.0
-
-[1] On Alpha, QEMU needs the gcc 'visibility' attribute only available
-    for gcc version >= 3.3.
-[2] Linux >= 2.4.20 is necessary for precise exception support
-    (untested).
-[3] 2.4.9-ac10-rmk2-np1-cerf2
-
-[4] gcc 2.95.x generates invalid code when using too many register
-variables. You must use gcc 3.x on PowerPC.
-@end example
+In order to compile QEMU successfully, it is very important that you
+have the right tools. The most important one is gcc. On most hosts and
+in particular on x86 ones, @emph{gcc 4.x is not supported}. If your
+Linux distribution includes a gcc 4.x compiler, you can usually
+install an older version (it is invoked by @code{gcc32} or
+@code{gcc34}). The QEMU configure script automatically probes for
+these older versions so that usally you don't have to do anything.
 
 @node Windows
 @section Windows
index c5a8e1a61ca19e09d94f34fbf79584d05de6dc4d..a25954649b106ef795bee8dc0d4707f7da9bcb26 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * create a COW disk image
+ * QEMU disk image utility
  * 
- * Copyright (c) 2003 Fabrice Bellard
+ * Copyright (c) 2003-2007 Fabrice Bellard
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -62,49 +62,6 @@ char *qemu_strdup(const char *str)
     return ptr;
 }
 
-void pstrcpy(char *buf, int buf_size, const char *str)
-{
-    int c;
-    char *q = buf;
-
-    if (buf_size <= 0)
-        return;
-
-    for(;;) {
-        c = *str++;
-        if (c == 0 || q >= buf + buf_size - 1)
-            break;
-        *q++ = c;
-    }
-    *q = '\0';
-}
-
-/* strcat and truncate. */
-char *pstrcat(char *buf, int buf_size, const char *s)
-{
-    int len;
-    len = strlen(buf);
-    if (len < buf_size) 
-        pstrcpy(buf + len, buf_size - len, s);
-    return buf;
-}
-
-int strstart(const char *str, const char *val, const char **ptr)
-{
-    const char *p, *q;
-    p = str;
-    q = val;
-    while (*q != '\0') {
-        if (*p != *q)
-            return 0;
-        p++;
-        q++;
-    }
-    if (ptr)
-        *ptr = p;
-    return 1;
-}
-
 void term_printf(const char *fmt, ...)
 {
     va_list ap;
@@ -113,6 +70,11 @@ void term_printf(const char *fmt, ...)
     va_end(ap);
 }
 
+void term_print_filename(const char *filename)
+{
+    term_printf(filename);
+}
+
 void __attribute__((noreturn)) error(const char *fmt, ...) 
 {
     va_list ap;
@@ -131,7 +93,7 @@ static void format_print(void *opaque, const char *name)
 
 void help(void)
 {
-    printf("qemu-img version " QEMU_VERSION ", Copyright (c) 2004-2005 Fabrice Bellard\n"
+    printf("qemu-img version " QEMU_VERSION ", Copyright (c) 2004-2007 Fabrice Bellard\n"
            "usage: qemu-img command [command options]\n"
            "QEMU disk image utility\n"
            "\n"
@@ -159,36 +121,6 @@ void help(void)
     exit(1);
 }
 
-
-#define NB_SUFFIXES 4
-
-static void get_human_readable_size(char *buf, int buf_size, int64_t size)
-{
-    static const char suffixes[NB_SUFFIXES] = "KMGT";
-    int64_t base;
-    int i;
-
-    if (size <= 999) {
-        snprintf(buf, buf_size, "%" PRId64, size);
-    } else {
-        base = 1024;
-        for(i = 0; i < NB_SUFFIXES; i++) {
-            if (size < (10 * base)) {
-                snprintf(buf, buf_size, "%0.1f%c", 
-                         (double)size / base,
-                         suffixes[i]);
-                break;
-            } else if (size < (1000 * base) || i == (NB_SUFFIXES - 1)) {
-                snprintf(buf, buf_size, "%" PRId64 "%c", 
-                         ((size + (base >> 1)) / base),
-                         suffixes[i]);
-                break;
-            }
-            base = base * 1024;
-        }
-    }
-}
-
 #if defined(WIN32)
 /* XXX: put correct support for win32 */
 static int read_password(char *buf, int buf_size)
@@ -486,6 +418,7 @@ static int img_convert(int argc, char **argv)
     int64_t total_sectors, nb_sectors, sector_num;
     uint8_t buf[IO_BUF_SIZE];
     const uint8_t *buf1;
+    BlockDriverInfo bdi;
 
     fmt = NULL;
     out_fmt = "raw";
@@ -525,9 +458,9 @@ static int img_convert(int argc, char **argv)
     drv = bdrv_find_format(out_fmt);
     if (!drv)
         error("Unknown file format '%s'", fmt);
-    if (compress && drv != &bdrv_qcow)
+    if (compress && drv != &bdrv_qcow && drv != &bdrv_qcow2)
         error("Compression not supported for this file format");
-    if (encrypt && drv != &bdrv_qcow)
+    if (encrypt && drv != &bdrv_qcow && drv != &bdrv_qcow2)
         error("Encryption not supported for this file format");
     if (compress && encrypt)
         error("Compression and encryption not supported at the same time");
@@ -544,7 +477,9 @@ static int img_convert(int argc, char **argv)
     out_bs = bdrv_new_open(out_filename, out_fmt);
 
     if (compress) {
-        cluster_size = qcow_get_cluster_size(out_bs);
+        if (bdrv_get_info(out_bs, &bdi) < 0)
+            error("could not get block driver info");
+        cluster_size = bdi.cluster_size;
         if (cluster_size <= 0 || cluster_size > IO_BUF_SIZE)
             error("invalid cluster size");
         cluster_sectors = cluster_size >> 9;
@@ -562,12 +497,15 @@ static int img_convert(int argc, char **argv)
             if (n < cluster_sectors)
                 memset(buf + n * 512, 0, cluster_size - n * 512);
             if (is_not_zero(buf, cluster_size)) {
-                if (qcow_compress_cluster(out_bs, sector_num, buf) != 0)
+                if (bdrv_write_compressed(out_bs, sector_num, buf, 
+                                          cluster_sectors) != 0)
                     error("error while compressing sector %" PRId64,
                           sector_num);
             }
             sector_num += n;
         }
+        /* signal EOF to align */
+        bdrv_write_compressed(out_bs, 0, NULL, 0);
     } else {
         sector_num = 0;
         for(;;) {
@@ -630,6 +568,24 @@ static int64_t get_allocated_file_size(const char *filename)
 }
 #endif
 
+static void dump_snapshots(BlockDriverState *bs)
+{
+    QEMUSnapshotInfo *sn_tab, *sn;
+    int nb_sns, i;
+    char buf[256];
+
+    nb_sns = bdrv_snapshot_list(bs, &sn_tab);
+    if (nb_sns <= 0)
+        return;
+    printf("Snapshot list:\n");
+    printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
+    for(i = 0; i < nb_sns; i++) {
+        sn = &sn_tab[i];
+        printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn));
+    }
+    qemu_free(sn_tab);
+}
+
 static int img_info(int argc, char **argv)
 {
     int c;
@@ -638,6 +594,9 @@ static int img_info(int argc, char **argv)
     BlockDriverState *bs;
     char fmt_name[128], size_buf[128], dsize_buf[128];
     int64_t total_sectors, allocated_size;
+    char backing_filename[1024];
+    char backing_filename2[1024];
+    BlockDriverInfo bdi;
 
     fmt = NULL;
     for(;;) {
@@ -688,6 +647,19 @@ static int img_info(int argc, char **argv)
            dsize_buf);
     if (bdrv_is_encrypted(bs))
         printf("encrypted: yes\n");
+    if (bdrv_get_info(bs, &bdi) >= 0) {
+        if (bdi.cluster_size != 0) 
+            printf("cluster_size: %d\n", bdi.cluster_size);
+    }
+    bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename));
+    if (backing_filename[0] != '\0') {
+        path_combine(backing_filename2, sizeof(backing_filename2),
+                     filename, backing_filename);
+        printf("backing file: %s (actual path: %s)\n", 
+               backing_filename,
+               backing_filename2);
+    }
+    dump_snapshots(bs);
     bdrv_delete(bs);
     return 0;
 }
index ac7923ffd1d7aa9dd645a46d9eec16d556adbc9a..1f01dce16263f41a78a0ae96922d8f75d9500b4c 100644 (file)
@@ -29,16 +29,19 @@ is the disk image format. It is guessed automatically in most cases. The followi
 @item raw
 
 Raw disk image format (default). This format has the advantage of
-being simple and easily exportable to all other emulators. If your file
-system supports @emph{holes} (for example in ext2 or ext3 on Linux),
-then only the written sectors will reserve space. Use @code{qemu-img
-info} to know the real size used by the image or @code{ls -ls} on
-Unix/Linux.
+being simple and easily exportable to all other emulators. If your
+file system supports @emph{holes} (for example in ext2 or ext3 on
+Linux or NTFS on Windows), then only the written sectors will reserve
+space. Use @code{qemu-img info} to know the real size used by the
+image or @code{ls -ls} on Unix/Linux.
 
-@item qcow
+@item qcow2
 QEMU image format, the most versatile format. Use it to have smaller
 images (useful if your filesystem does not supports holes, for example
-on Windows), optional AES encryption and zlib based compression.
+on Windows), optional AES encryption, zlib based compression and
+support of multiple VM snapshots.
+@item qcow
+Old QEMU image format. Left for compatibility.
 @item cow
 User Mode Linux Copy On Write image format. Used to be the only growable
 image format in QEMU. It is supported only for compatibility with
@@ -104,7 +107,8 @@ are detected and suppressed from the destination image.
 
 Give information about the disk image @var{filename}. Use it in
 particular to know the size reserved on disk which can be different
-from the displayed size.
+from the displayed size. If VM snapshots are stored in the disk image,
+they are displayed too.
 @end table
 
 @c man end
index 64b7d4e5ef459daa6e3a904af152530a748c46ee..6e8bcce6cf4c5cc2842cf8b00e2f96ce6c713b58 100644 (file)
@@ -19,6 +19,7 @@
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <netinet/tcp.h>
+#include <sys/un.h>
 
 #define socket_error() errno
 #define closesocket(s) close(s)
index f43569f1ad844d8f306181f646b90cc40ec387aa..4d6d73a6a12de4e568cfb145394d7d4d89d0b03c 100644 (file)
@@ -104,6 +104,10 @@ static uint8_t sdl_keyevent_to_keycode_generic(const SDL_KeyboardEvent *ev)
     keysym = ev->keysym.sym;
     if (keysym == 0 && ev->keysym.scancode == 113)
         keysym = SDLK_MODE;
+    /* For Japanese key '\' and '|' */
+    if (keysym == 92 && ev->keysym.scancode == 133) {
+        keysym = 0xa5;
+    }
     return keysym2scancode(kbd_layout, keysym);
 }
 
@@ -118,70 +122,6 @@ static uint8_t sdl_keyevent_to_keycode(const SDL_KeyboardEvent *ev)
 
 #else
 
-static const uint8_t x_keycode_to_pc_keycode[61] = {
-   0xc7,      /*  97  Home   */
-   0xc8,      /*  98  Up     */
-   0xc9,      /*  99  PgUp   */
-   0xcb,      /* 100  Left   */
-   0x4c,        /* 101  KP-5   */
-   0xcd,      /* 102  Right  */
-   0xcf,      /* 103  End    */
-   0xd0,      /* 104  Down   */
-   0xd1,      /* 105  PgDn   */
-   0xd2,      /* 106  Ins    */
-   0xd3,      /* 107  Del    */
-   0x9c,      /* 108  Enter  */
-   0x9d,      /* 109  Ctrl-R */
-   0x0,       /* 110  Pause  */
-   0xb7,      /* 111  Print  */
-   0xb5,      /* 112  Divide */
-   0xb8,      /* 113  Alt-R  */
-   0xc6,      /* 114  Break  */   
-   0x0,         /* 115 */
-   0x0,         /* 116 */
-   0x0,         /* 117 */
-   0x0,         /* 118 */
-   0x0,         /* 119 */
-   0x70,         /* 120 Hiragana_Katakana */
-   0x0,         /* 121 */
-   0x0,         /* 122 */
-   0x73,         /* 123 backslash */
-   0x0,         /* 124 */
-   0x0,         /* 125 */
-   0x0,         /* 126 */
-   0x0,         /* 127 */
-   0x0,         /* 128 */
-   0x79,         /* 129 Henkan */
-   0x0,         /* 130 */
-   0x7b,         /* 131 Muhenkan */
-   0x0,         /* 132 */
-   0x7d,         /* 133 Yen */
-   0x0,         /* 134 */
-   0x0,         /* 135 */
-   0x47,         /* 136 KP_7 */
-   0x48,         /* 137 KP_8 */
-   0x49,         /* 138 KP_9 */
-   0x4b,         /* 139 KP_4 */
-   0x4c,         /* 140 KP_5 */
-   0x4d,         /* 141 KP_6 */
-   0x4f,         /* 142 KP_1 */
-   0x50,         /* 143 KP_2 */
-   0x51,         /* 144 KP_3 */
-   0x52,         /* 145 KP_0 */
-   0x53,         /* 146 KP_. */
-   0x47,         /* 147 KP_HOME */
-   0x48,         /* 148 KP_UP */
-   0x49,         /* 149 KP_PgUp */
-   0x4b,         /* 150 KP_Left */
-   0x4c,         /* 151 KP_ */
-   0x4d,         /* 152 KP_Right */
-   0x4f,         /* 153 KP_End */
-   0x50,         /* 154 KP_Down */
-   0x51,         /* 155 KP_PgDn */
-   0x52,         /* 156 KP_Ins */
-   0x53,         /* 157 KP_Del */
-};
-
 static uint8_t sdl_keyevent_to_keycode(const SDL_KeyboardEvent *ev)
 {
     int keycode;
@@ -192,9 +132,9 @@ static uint8_t sdl_keyevent_to_keycode(const SDL_KeyboardEvent *ev)
         keycode = 0;
     } else if (keycode < 97) {
         keycode -= 8; /* just an offset */
-    } else if (keycode < 158) {
+    } else if (keycode < 212) {
         /* use conversion table */
-        keycode = x_keycode_to_pc_keycode[keycode - 97];
+        keycode = _translate_keycode(keycode - 97);
     } else {
         keycode = 0;
     }
@@ -297,6 +237,7 @@ static void sdl_show_cursor(void)
 {
     if (!kbd_mouse_is_absolute()) {
         SDL_ShowCursor(1);
+        SDL_SetCursor(sdl_cursor_normal);
     }
 }
 
@@ -342,6 +283,9 @@ static void sdl_send_mouse_event(int dz)
        SDL_GetMouseState(&dx, &dy);
        dx = dx * 0x7FFF / width;
        dy = dy * 0x7FFF / height;
+    } else if (absolute_enabled) {
+       sdl_show_cursor();
+       absolute_enabled = 0;
     }
 
     kbd_mouse_event(dx, dy, dz, buttons);
@@ -394,6 +338,8 @@ static void sdl_refresh(DisplayState *ds)
                         gui_keysym = 1;
                         break;
                     case 0x02 ... 0x0a: /* '1' to '9' keys */ 
+                        /* Reset the modifiers sent to the current console */
+                        reset_keys();
                         console_select(keycode - 0x02);
                         if (!is_graphic_console()) {
                             /* display grab if going to a text console */
@@ -468,14 +414,17 @@ static void sdl_refresh(DisplayState *ds)
                     }
                 }
             }
-            if (is_graphic_console()) 
+            if (is_graphic_console() && !gui_keysym
                 sdl_process_key(&ev->key);
             break;
         case SDL_QUIT:
-            qemu_system_shutdown_request();
+            if (!no_quit) {
+               qemu_system_shutdown_request();
+            }
             break;
         case SDL_MOUSEMOTION:
-            if (gui_grab || kbd_mouse_is_absolute()) {
+            if (gui_grab || kbd_mouse_is_absolute() ||
+                absolute_enabled) {
                 sdl_send_mouse_event(0);
             }
             break;
index af5e25e6832c68f7882ceb9abf3ef7ce37f26a5a..d84a622d355f94bdff1519d063190254bea23d5e 100644 (file)
@@ -97,6 +97,7 @@ typedef struct tap_win32_overlapped {
     HANDLE write_event;
     HANDLE output_queue_semaphore;
     HANDLE free_list_semaphore;
+    HANDLE tap_semaphore;
     CRITICAL_SECTION output_queue_cs;
     CRITICAL_SECTION free_list_cs;
     OVERLAPPED read_overlapped;
@@ -445,6 +446,10 @@ static void tap_win32_overlapped_init(tap_win32_overlapped_t* const overlapped,
             overlapped->free_list = element;
         }
     }
+    /* To count buffers, initially no-signal. */
+    overlapped->tap_semaphore = CreateSemaphore(NULL, 0, TUN_MAX_BUFFER_COUNT, NULL);
+    if(!overlapped->tap_semaphore)
+        fprintf(stderr, "error creating tap_semaphore.\n");
 }
 
 static int tap_win32_write(tap_win32_overlapped_t *overlapped, 
@@ -526,6 +531,7 @@ static DWORD WINAPI tap_win32_thread_entry(LPVOID param)
         if(read_size > 0) {
             buffer->read_size = read_size;
             put_buffer_on_output_queue(overlapped, buffer);
+            ReleaseSemaphore(overlapped->tap_semaphore, 1, NULL);
             buffer = get_buffer_from_free_list(overlapped);
         }
     }
@@ -620,8 +626,6 @@ static int tap_win32_open(tap_win32_overlapped_t **phandle,
 
     hThread = CreateThread(NULL, 0, tap_win32_thread_entry,
                            (LPVOID)&tap_overlapped, 0, &idThread);
-    SetThreadPriority(hThread,THREAD_PRIORITY_TIME_CRITICAL);
-
     return 0;
 }
 
@@ -630,11 +634,8 @@ static int tap_win32_open(tap_win32_overlapped_t **phandle,
  typedef struct TAPState {
      VLANClientState *vc;
      tap_win32_overlapped_t *handle;
-     HANDLE tap_event;
  } TAPState;
 
-static TAPState *tap_win32_state = NULL;
-
 static void tap_receive(void *opaque, const uint8_t *buf, int size)
 {
     TAPState *s = opaque;
@@ -642,22 +643,17 @@ static void tap_receive(void *opaque, const uint8_t *buf, int size)
     tap_win32_write(s->handle, buf, size);
 }
 
-/* XXX: horrible, suppress this by using proper thread signaling */
-void tap_win32_poll(void)
+static void tap_win32_send(void *opaque)
 {
-    TAPState *s = tap_win32_state;
+    TAPState *s = opaque;
     uint8_t *buf;
     int max_size = 4096;
     int size;
 
-    if (!s)
-        return;
-
     size = tap_win32_read(s->handle, &buf, max_size);
     if (size > 0) {
         qemu_send_packet(s->vc, buf, size);
         tap_win32_free_buffer(s->handle, buf);
-        SetEvent(s->tap_event);
     }
 }
 
@@ -677,12 +673,7 @@ int tap_win32_init(VLANState *vlan, const char *ifname)
     
     snprintf(s->vc->info_str, sizeof(s->vc->info_str),
              "tap: ifname=%s", ifname);
-    tap_win32_state = s;
 
-    s->tap_event = CreateEvent(NULL, FALSE, FALSE, NULL);
-    if (!s->tap_event) {
-        fprintf(stderr, "tap-win32: Failed CreateEvent\n");
-    }
-    qemu_add_wait_object(s->tap_event, NULL, NULL);
+    qemu_add_wait_object(s->handle->tap_semaphore, tap_win32_send, s);
     return 0;
 }
index 513d925b732d2c811119eb1ab5fdf377c98b8b8c..c5a2ba9ad064cf0c6b0a7c9462b99b1fa9badcee 100644 (file)
@@ -633,13 +633,9 @@ int main_loop(void)
     handle_buffered_io(env);
     main_loop_wait(1); /* For the select() on events */
 
-    /* Stop the IDE thread */
-    ide_stop_dma_thread();
-
     /* Save the device state */
     sprintf(qemu_file, "/tmp/xen.qemu-dm.%d", domid);
-    if (qemu_savevm(qemu_file) < 0)
-        fprintf(stderr, "qemu save fail.\n");
+    do_savevm(qemu_file);
 
     return 0;
 }
index e5851d3f968c7e569e2660483209815a485e2414..82ee0551ccac9cfd8a44907e5d461592e047a64f 100644 (file)
@@ -40,20 +40,60 @@ static uint32_t i440fx_addr_readl(void* opaque, uint32_t addr)
     return s->config_reg;
 }
 
-static void i440fx_set_irq(PCIDevice *pci_dev, void *pic, int intx, int level)
+/* return the global irq number corresponding to a given device irq
+   pin. We could also use the bus number to have a more precise
+   mapping. */
+static int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
 {
-    xc_hvm_set_pci_intx_level(xc_handle, domid, 0, 0, pci_dev->devfn >> 3,
-                              intx, level);
+#ifndef CONFIG_DM
+    int slot_addend;
+    slot_addend = (pci_dev->devfn >> 3) - 1;
+    return (irq_num + slot_addend) & 3;
+#else  /* !CONFIG_DM */
+    return irq_num + ((pci_dev->devfn >> 3) << 2);
+#endif /* !CONFIG_DM */
 }
 
-PCIBus *i440fx_init(void)
+static void i440fx_set_irq(void *pic, int irq_num, int level)
+{
+    xc_hvm_set_pci_intx_level(xc_handle, domid, 0, 0, irq_num >> 2,
+                              irq_num & 3, level);
+}
+
+static void i440fx_save(QEMUFile* f, void *opaque)
+{
+    PCIDevice *d = opaque;
+    pci_device_save(d, f);
+#ifndef CONFIG_DM
+    qemu_put_8s(f, &smm_enabled);
+#endif /* !CONFIG_DM */
+}
+
+static int i440fx_load(QEMUFile* f, void *opaque, int version_id)
+{
+    PCIDevice *d = opaque;
+    int ret;
+
+    if (version_id != 1)
+        return -EINVAL;
+    ret = pci_device_load(d, f);
+    if (ret < 0)
+        return ret;
+#ifndef CONFIG_DM
+    i440fx_update_memory_mappings(d);
+    qemu_get_8s(f, &smm_enabled);
+#endif /* !CONFIG_DM */
+    return 0;
+}
+
+PCIBus *i440fx_init(PCIDevice **pi440fx_state)
 {
     PCIBus *b;
     PCIDevice *d;
     I440FXState *s;
 
     s = qemu_mallocz(sizeof(I440FXState));
-    b = pci_register_bus(i440fx_set_irq, NULL, 0);
+    b = pci_register_bus(i440fx_set_irq, pci_slot_get_pirq, NULL, 0, 128);
     s->bus = b;
 
     register_ioport_write(0xcf8, 4, 4, i440fx_addr_writel, s);
@@ -77,6 +117,9 @@ PCIBus *i440fx_init(void)
     d->config[0x0a] = 0x00; // class_sub = host2pci
     d->config[0x0b] = 0x06; // class_base = PCI_bridge
     d->config[0x0e] = 0x00; // header_type
+
+    register_savevm("I440FX", 0, 1, i440fx_save, i440fx_load, d);
+    *pi440fx_state = d;
     return b;
 }
 
@@ -108,9 +151,12 @@ static void piix3_reset(PCIDevice *d)
     uint8_t *pci_conf = d->config;
 
     pci_conf[0x04] = 0x07; // master, memory and I/O
+    pci_conf[0x05] = 0x00;
+    pci_conf[0x06] = 0x00;
     pci_conf[0x07] = 0x02; // PCI_status_devsel_medium
     pci_conf[0x4c] = 0x4d;
     pci_conf[0x4e] = 0x03;
+    pci_conf[0x4f] = 0x00;
     pci_conf[0x60] = 0x80;
     pci_conf[0x61] = 0x80;
     pci_conf[0x62] = 0x80;
@@ -120,19 +166,45 @@ static void piix3_reset(PCIDevice *d)
     pci_conf[0x76] = 0x0c;
     pci_conf[0x77] = 0x0c;
     pci_conf[0x78] = 0x02;
+    pci_conf[0x79] = 0x00;
+    pci_conf[0x80] = 0x00;
+    pci_conf[0x82] = 0x00;
     pci_conf[0xa0] = 0x08;
-    pci_conf[0xa0] = 0x08;
+    pci_conf[0xa2] = 0x00;
+    pci_conf[0xa3] = 0x00;
+    pci_conf[0xa4] = 0x00;
+    pci_conf[0xa5] = 0x00;
+    pci_conf[0xa6] = 0x00;
+    pci_conf[0xa7] = 0x00;
     pci_conf[0xa8] = 0x0f;
+    pci_conf[0xaa] = 0x00;
+    pci_conf[0xab] = 0x00;
+    pci_conf[0xac] = 0x00;
+    pci_conf[0xae] = 0x00;
+}
+
+static void piix_save(QEMUFile* f, void *opaque)
+{
+    PCIDevice *d = opaque;
+    pci_device_save(d, f);
 }
 
-int piix3_init(PCIBus *bus)
+static int piix_load(QEMUFile* f, void *opaque, int version_id)
+{
+    PCIDevice *d = opaque;
+    if (version_id != 2)
+        return -EINVAL;
+    return pci_device_load(d, f);
+}
+
+int piix3_init(PCIBus *bus, int devfn)
 {
     PCIDevice *d;
     uint8_t *pci_conf;
 
     d = pci_register_device(bus, "PIIX3", sizeof(PCIDevice),
-                                    -1, NULL, piix3_write_config);
-    register_savevm("PIIX3", 0, 1, generic_pci_save, generic_pci_load, d);
+                                    devfn, NULL, piix3_write_config);
+    register_savevm("PIIX3", 0, 2, piix_save, piix_load, d);
 
     piix3_dev = d;
     pci_conf = d->config;
@@ -148,5 +220,3 @@ int piix3_init(PCIBus *bus)
     piix3_reset(d);
     return d->devfn;
 }
-
-void pci_bios_init(void) {}
index e8be999dba20b458a8869eaff374628e6832f6fd..ee3a3c4251cf287f7e9b351eb20255d78db8043d 100644 (file)
 
 #include "vl.h"
 
-//#define DEBUG_CMOS
+// #define DEBUG_CMOS
 
 struct RTCState {
     uint8_t cmos_data[128];
     uint8_t cmos_index;
 };
 
+static inline int to_bcd(RTCState *s, int a)
+{
+    return ((a / 10) << 4) | (a % 10);
+}
+
 void rtc_set_memory(RTCState *s, int addr, int val)
 {
     if (addr >= 0 && addr <= 127)
@@ -92,11 +97,23 @@ static int rtc_load(QEMUFile *f, void *opaque, int version_id)
 RTCState *rtc_init(int base, int irq)
 {
     RTCState *s;
+    time_t ti;
+    struct tm *tm;
+    int val;
 
     s = qemu_mallocz(sizeof(RTCState));
     if (!s)
         return NULL;
 
+/* PC cmos mappings */
+#define REG_IBM_CENTURY_BYTE        0x32
+#define REG_IBM_PS2_CENTURY_BYTE    0x37
+    time(&ti);
+    tm = gmtime(&ti);          /* XXX localtime and update from guest? */
+    val = to_bcd(s, (tm->tm_year / 100) + 19);
+    rtc_set_memory(s, REG_IBM_CENTURY_BYTE, val);
+    rtc_set_memory(s, REG_IBM_PS2_CENTURY_BYTE, val);
+
     register_ioport_write(base, 2, 1, cmos_ioport_write, s);
     register_ioport_read(base, 2, 1, cmos_ioport_read, s);
 
index e7b571fd99df2a0dea745838b093bde18ddf9628..c1573dee5512a7b866b0fb80807fa738b9aff3a2 100644 (file)
@@ -1,13 +1,13 @@
-/cpu.h/1.36/Wed Jul 26 12:39:11 2006//Trelease_0_8_2
-/exec.h/1.30/Sun Aug  6 01:04:03 2006//Trelease_0_8_2
-/helper.c/1.69/Sun Aug  6 01:04:03 2006//Trelease_0_8_2
-/helper2.c/1.43/Sun Aug  6 01:04:03 2006//Trelease_0_8_2
-/op.c/1.45/Sun Aug  6 01:04:03 2006//Trelease_0_8_2
-/opreg_template.h/1.3/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
-/ops_mem.h/1.7/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
-/ops_sse.h/1.6/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
-/ops_template.h/1.10/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
-/ops_template_mem.h/1.6/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
-/translate-copy.c/1.7/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
-/translate.c/1.59/Sun Aug  6 01:04:03 2006//Trelease_0_8_2
+/cpu.h/1.41/Thu May  3 17:18:12 2007//Trelease_0_9_0
+/exec.h/1.31/Thu May  3 17:18:12 2007//Trelease_0_9_0
+/helper.c/1.74/Thu May  3 17:18:12 2007//Trelease_0_9_0
+/helper2.c/1.45/Thu May  3 17:18:12 2007//Trelease_0_9_0
+/op.c/1.47/Thu May  3 17:18:12 2007//Trelease_0_9_0
+/opreg_template.h/1.3/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/ops_mem.h/1.7/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/ops_sse.h/1.7/Thu May  3 17:18:12 2007//Trelease_0_9_0
+/ops_template.h/1.10/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/ops_template_mem.h/1.6/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/translate-copy.c/1.7/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/translate.c/1.62/Thu May  3 17:18:12 2007//Trelease_0_9_0
 D
index bd48d406fa1b16a1721b34dc4bb6979acc4274da..eed9f4a4fb93e992c8c20b591822041f09711c7e 100644 (file)
@@ -1 +1 @@
-Nrelease_0_8_2
+Nrelease_0_9_0
index 2f23617303e346ab4d8534ca9f6c2b4cfd17cccb..1eb546e5667c287fad215adba9bb1c69892a058c 100644 (file)
 
 #define TARGET_HAS_ICE 1
 
+#ifdef TARGET_X86_64
+#define ELF_MACHINE    EM_X86_64
+#else
+#define ELF_MACHINE    EM_386
+#endif
+
 #include "cpu-defs.h"
 
 #include "softfloat.h"
 
-#if defined(__i386__) && !defined(CONFIG_SOFTMMU)
+#if defined(__i386__) && !defined(CONFIG_SOFTMMU) && !defined(__APPLE__)
 #define USE_CODE_COPY
 #endif
 
 #define HF_OSFXSR_SHIFT     16 /* CR4.OSFXSR */
 #define HF_VM_SHIFT         17 /* must be same as eflags */
 #define HF_HALTED_SHIFT     18 /* CPU halted */
+#define HF_SMM_SHIFT        19 /* CPU in SMM mode */
 
 #define HF_CPL_MASK          (3 << HF_CPL_SHIFT)
 #define HF_SOFTMMU_MASK      (1 << HF_SOFTMMU_SHIFT)
 #define HF_CS64_MASK         (1 << HF_CS64_SHIFT)
 #define HF_OSFXSR_MASK       (1 << HF_OSFXSR_SHIFT)
 #define HF_HALTED_MASK       (1 << HF_HALTED_SHIFT)
+#define HF_SMM_MASK          (1 << HF_SMM_SHIFT)
 
 #define CR0_PE_MASK  (1 << 0)
 #define CR0_MP_MASK  (1 << 1)
 #define CPUID_MCA  (1 << 14)
 #define CPUID_CMOV (1 << 15)
 #define CPUID_PAT  (1 << 16)
+#define CPUID_PSE36   (1 << 17)
 #define CPUID_CLFLUSH (1 << 19)
 /* ... */
 #define CPUID_MMX  (1 << 23)
@@ -503,6 +512,7 @@ typedef struct CPUX86State {
     int exception_is_int;
     target_ulong exception_next_eip;
     target_ulong dr[8]; /* debug registers */
+    uint32_t smbase;
     int interrupt_request; 
     int user_mode_only; /* user mode only simulation */
 
@@ -540,7 +550,8 @@ void cpu_set_ferr(CPUX86State *s);
    cache: it synchronizes the hflags with the segment cache values */
 static inline void cpu_x86_load_seg_cache(CPUX86State *env, 
                                           int seg_reg, unsigned int selector,
-                                          uint32_t base, unsigned int limit, 
+                                          target_ulong base,
+                                          unsigned int limit, 
                                           unsigned int flags)
 {
     SegmentCache *sc;
@@ -617,8 +628,7 @@ void cpu_x86_frstor(CPUX86State *s, uint8_t *ptr, int data32);
 /* you can call this signal handler from your SIGBUS and SIGSEGV
    signal handlers to inform the virtual CPU of exceptions. non zero
    is returned if the signal was handled by the virtual CPU.  */
-struct siginfo;
-int cpu_x86_signal_handler(int host_signum, struct siginfo *info, 
+int cpu_x86_signal_handler(int host_signum, void *pinfo, 
                            void *puc);
 void cpu_x86_set_a20(CPUX86State *env, int a20_state);
 
@@ -630,6 +640,7 @@ void cpu_set_apic_tpr(CPUX86State *env, uint8_t val);
 #ifndef NO_CPU_IO_DEFS
 uint8_t cpu_get_apic_tpr(CPUX86State *env);
 #endif
+void cpu_smm_update(CPUX86State *env);
 
 /* will be suppressed */
 void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0);
index 609a5869a076e8c81eb1c81d67590b575dd9cf91..377f7bd28b953c43b03192defbfe47fe1b9d43e9 100644 (file)
@@ -176,6 +176,7 @@ void raise_interrupt(int intno, int is_int, int error_code,
                      int next_eip_addend);
 void raise_exception_err(int exception_index, int error_code);
 void raise_exception(int exception_index);
+void do_smm_enter(void);
 void __hidden cpu_loop_exit(void);
 
 void OPPROTO op_movl_eflags_T0(void);
@@ -203,6 +204,7 @@ void helper_lsl(void);
 void helper_lar(void);
 void helper_verr(void);
 void helper_verw(void);
+void helper_rsm(void);
 
 void check_iob_T0(void);
 void check_iow_T0(void);
index 70e9fae3b0e272ef6c4ef7fab5b1537d617db7d9..1d62f6b2e3d43d5247c053dabb71f6fea936a5c9 100644 (file)
@@ -553,6 +553,20 @@ static inline unsigned int get_sp_mask(unsigned int e2)
         return 0xffff;
 }
 
+#ifdef TARGET_X86_64
+#define SET_ESP(val, sp_mask)\
+do {\
+    if ((sp_mask) == 0xffff)\
+        ESP = (ESP & ~0xffff) | ((val) & 0xffff);\
+    else if ((sp_mask) == 0xffffffffLL)\
+        ESP = (uint32_t)(val);\
+    else\
+        ESP = (val);\
+} while (0)
+#else
+#define SET_ESP(val, sp_mask) ESP = (ESP & ~(sp_mask)) | ((val) & (sp_mask))
+#endif
+
 /* XXX: add a is_user flag to have proper security support */
 #define PUSHW(ssp, sp, sp_mask, val)\
 {\
@@ -584,10 +598,10 @@ static void do_interrupt_protected(int intno, int is_int, int error_code,
 {
     SegmentCache *dt;
     target_ulong ptr, ssp;
-    int type, dpl, selector, ss_dpl, cpl, sp_mask;
+    int type, dpl, selector, ss_dpl, cpl;
     int has_error_code, new_stack, shift;
     uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2;
-    uint32_t old_eip;
+    uint32_t old_eip, sp_mask;
 
     has_error_code = 0;
     if (!is_int && !is_hw) {
@@ -623,7 +637,8 @@ static void do_interrupt_protected(int intno, int is_int, int error_code,
             raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2);
         switch_tss(intno * 8, e1, e2, SWITCH_TSS_CALL, old_eip);
         if (has_error_code) {
-            int mask, type;
+            int type;
+            uint32_t mask;
             /* push the error code */
             type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
             shift = type >> 3;
@@ -637,7 +652,7 @@ static void do_interrupt_protected(int intno, int is_int, int error_code,
                 stl_kernel(ssp, error_code);
             else
                 stw_kernel(ssp, error_code);
-            ESP = (esp & mask) | (ESP & ~mask);
+            SET_ESP(esp, mask);
         }
         return;
     case 6: /* 286 interrupt gate */
@@ -765,7 +780,7 @@ static void do_interrupt_protected(int intno, int is_int, int error_code,
         cpu_x86_load_seg_cache(env, R_SS, ss, 
                                ssp, get_seg_limit(ss_e1, ss_e2), ss_e2);
     }
-    ESP = (ESP & ~sp_mask) | (esp & sp_mask);
+    SET_ESP(esp, sp_mask);
 
     selector = (selector & ~3) | dpl;
     cpu_x86_load_seg_cache(env, R_CS, selector, 
@@ -962,7 +977,7 @@ void helper_syscall(int next_eip_addend)
         cpu_x86_set_cpl(env, 0);
         cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc, 
                            0, 0xffffffff, 
-                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
+                               DESC_G_MASK | DESC_P_MASK |
                                DESC_S_MASK |
                                DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
         cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc, 
@@ -1013,7 +1028,7 @@ void helper_sysret(int dflag)
         if (dflag == 2) {
             cpu_x86_load_seg_cache(env, R_CS, (selector + 16) | 3, 
                                    0, 0xffffffff, 
-                                   DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
+                                   DESC_G_MASK | DESC_P_MASK |
                                    DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
                                    DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | 
                                    DESC_L_MASK);
@@ -1215,6 +1230,289 @@ void raise_exception(int exception_index)
     raise_interrupt(exception_index, 0, 0, 0);
 }
 
+/* SMM support */
+
+#if defined(CONFIG_USER_ONLY) 
+
+void do_smm_enter(void)
+{
+}
+
+void helper_rsm(void)
+{
+}
+
+#else
+
+#ifdef TARGET_X86_64
+#define SMM_REVISION_ID 0x00020064
+#else
+#define SMM_REVISION_ID 0x00020000
+#endif
+
+void do_smm_enter(void)
+{
+    target_ulong sm_state;
+    SegmentCache *dt;
+    int i, offset;
+
+    if (loglevel & CPU_LOG_INT) {
+        fprintf(logfile, "SMM: enter\n");
+        cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
+    }
+
+    env->hflags |= HF_SMM_MASK;
+    cpu_smm_update(env);
+
+    sm_state = env->smbase + 0x8000;
+    
+#ifdef TARGET_X86_64
+    for(i = 0; i < 6; i++) {
+        dt = &env->segs[i];
+        offset = 0x7e00 + i * 16;
+        stw_phys(sm_state + offset, dt->selector);
+        stw_phys(sm_state + offset + 2, (dt->flags >> 8) & 0xf0ff);
+        stl_phys(sm_state + offset + 4, dt->limit);
+        stq_phys(sm_state + offset + 8, dt->base);
+    }
+
+    stq_phys(sm_state + 0x7e68, env->gdt.base);
+    stl_phys(sm_state + 0x7e64, env->gdt.limit);
+
+    stw_phys(sm_state + 0x7e70, env->ldt.selector);
+    stq_phys(sm_state + 0x7e78, env->ldt.base);
+    stl_phys(sm_state + 0x7e74, env->ldt.limit);
+    stw_phys(sm_state + 0x7e72, (env->ldt.flags >> 8) & 0xf0ff);
+    
+    stq_phys(sm_state + 0x7e88, env->idt.base);
+    stl_phys(sm_state + 0x7e84, env->idt.limit);
+
+    stw_phys(sm_state + 0x7e90, env->tr.selector);
+    stq_phys(sm_state + 0x7e98, env->tr.base);
+    stl_phys(sm_state + 0x7e94, env->tr.limit);
+    stw_phys(sm_state + 0x7e92, (env->tr.flags >> 8) & 0xf0ff);
+    
+    stq_phys(sm_state + 0x7ed0, env->efer);
+
+    stq_phys(sm_state + 0x7ff8, EAX);
+    stq_phys(sm_state + 0x7ff0, ECX);
+    stq_phys(sm_state + 0x7fe8, EDX);
+    stq_phys(sm_state + 0x7fe0, EBX);
+    stq_phys(sm_state + 0x7fd8, ESP);
+    stq_phys(sm_state + 0x7fd0, EBP);
+    stq_phys(sm_state + 0x7fc8, ESI);
+    stq_phys(sm_state + 0x7fc0, EDI);
+    for(i = 8; i < 16; i++) 
+        stq_phys(sm_state + 0x7ff8 - i * 8, env->regs[i]);
+    stq_phys(sm_state + 0x7f78, env->eip);
+    stl_phys(sm_state + 0x7f70, compute_eflags());
+    stl_phys(sm_state + 0x7f68, env->dr[6]);
+    stl_phys(sm_state + 0x7f60, env->dr[7]);
+
+    stl_phys(sm_state + 0x7f48, env->cr[4]);
+    stl_phys(sm_state + 0x7f50, env->cr[3]);
+    stl_phys(sm_state + 0x7f58, env->cr[0]);
+
+    stl_phys(sm_state + 0x7efc, SMM_REVISION_ID);
+    stl_phys(sm_state + 0x7f00, env->smbase);
+#else
+    stl_phys(sm_state + 0x7ffc, env->cr[0]);
+    stl_phys(sm_state + 0x7ff8, env->cr[3]);
+    stl_phys(sm_state + 0x7ff4, compute_eflags());
+    stl_phys(sm_state + 0x7ff0, env->eip);
+    stl_phys(sm_state + 0x7fec, EDI);
+    stl_phys(sm_state + 0x7fe8, ESI);
+    stl_phys(sm_state + 0x7fe4, EBP);
+    stl_phys(sm_state + 0x7fe0, ESP);
+    stl_phys(sm_state + 0x7fdc, EBX);
+    stl_phys(sm_state + 0x7fd8, EDX);
+    stl_phys(sm_state + 0x7fd4, ECX);
+    stl_phys(sm_state + 0x7fd0, EAX);
+    stl_phys(sm_state + 0x7fcc, env->dr[6]);
+    stl_phys(sm_state + 0x7fc8, env->dr[7]);
+    
+    stl_phys(sm_state + 0x7fc4, env->tr.selector);
+    stl_phys(sm_state + 0x7f64, env->tr.base);
+    stl_phys(sm_state + 0x7f60, env->tr.limit);
+    stl_phys(sm_state + 0x7f5c, (env->tr.flags >> 8) & 0xf0ff);
+    
+    stl_phys(sm_state + 0x7fc0, env->ldt.selector);
+    stl_phys(sm_state + 0x7f80, env->ldt.base);
+    stl_phys(sm_state + 0x7f7c, env->ldt.limit);
+    stl_phys(sm_state + 0x7f78, (env->ldt.flags >> 8) & 0xf0ff);
+    
+    stl_phys(sm_state + 0x7f74, env->gdt.base);
+    stl_phys(sm_state + 0x7f70, env->gdt.limit);
+
+    stl_phys(sm_state + 0x7f58, env->idt.base);
+    stl_phys(sm_state + 0x7f54, env->idt.limit);
+
+    for(i = 0; i < 6; i++) {
+        dt = &env->segs[i];
+        if (i < 3)
+            offset = 0x7f84 + i * 12;
+        else
+            offset = 0x7f2c + (i - 3) * 12;
+        stl_phys(sm_state + 0x7fa8 + i * 4, dt->selector);
+        stl_phys(sm_state + offset + 8, dt->base);
+        stl_phys(sm_state + offset + 4, dt->limit);
+        stl_phys(sm_state + offset, (dt->flags >> 8) & 0xf0ff);
+    }
+    stl_phys(sm_state + 0x7f14, env->cr[4]);
+
+    stl_phys(sm_state + 0x7efc, SMM_REVISION_ID);
+    stl_phys(sm_state + 0x7ef8, env->smbase);
+#endif
+    /* init SMM cpu state */
+
+#ifdef TARGET_X86_64
+    env->efer = 0;
+    env->hflags &= ~HF_LMA_MASK;
+#endif
+    load_eflags(0, ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
+    env->eip = 0x00008000;
+    cpu_x86_load_seg_cache(env, R_CS, (env->smbase >> 4) & 0xffff, env->smbase,
+                           0xffffffff, 0);
+    cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffffffff, 0);
+    cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffffffff, 0);
+    cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffffffff, 0);
+    cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffffffff, 0);
+    cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffffffff, 0);
+    
+    cpu_x86_update_cr0(env, 
+                       env->cr[0] & ~(CR0_PE_MASK | CR0_EM_MASK | CR0_TS_MASK | CR0_PG_MASK));
+    cpu_x86_update_cr4(env, 0);
+    env->dr[7] = 0x00000400;
+    CC_OP = CC_OP_EFLAGS;
+}
+
+void helper_rsm(void)
+{
+    target_ulong sm_state;
+    int i, offset;
+    uint32_t val;
+
+    sm_state = env->smbase + 0x8000;
+#ifdef TARGET_X86_64
+    env->efer = ldq_phys(sm_state + 0x7ed0);
+    if (env->efer & MSR_EFER_LMA)
+        env->hflags |= HF_LMA_MASK;
+    else
+        env->hflags &= ~HF_LMA_MASK;
+
+    for(i = 0; i < 6; i++) {
+        offset = 0x7e00 + i * 16;
+        cpu_x86_load_seg_cache(env, i, 
+                               lduw_phys(sm_state + offset),
+                               ldq_phys(sm_state + offset + 8),
+                               ldl_phys(sm_state + offset + 4),
+                               (lduw_phys(sm_state + offset + 2) & 0xf0ff) << 8);
+    }
+
+    env->gdt.base = ldq_phys(sm_state + 0x7e68);
+    env->gdt.limit = ldl_phys(sm_state + 0x7e64);
+
+    env->ldt.selector = lduw_phys(sm_state + 0x7e70);
+    env->ldt.base = ldq_phys(sm_state + 0x7e78);
+    env->ldt.limit = ldl_phys(sm_state + 0x7e74);
+    env->ldt.flags = (lduw_phys(sm_state + 0x7e72) & 0xf0ff) << 8;
+    
+    env->idt.base = ldq_phys(sm_state + 0x7e88);
+    env->idt.limit = ldl_phys(sm_state + 0x7e84);
+
+    env->tr.selector = lduw_phys(sm_state + 0x7e90);
+    env->tr.base = ldq_phys(sm_state + 0x7e98);
+    env->tr.limit = ldl_phys(sm_state + 0x7e94);
+    env->tr.flags = (lduw_phys(sm_state + 0x7e92) & 0xf0ff) << 8;
+    
+    EAX = ldq_phys(sm_state + 0x7ff8);
+    ECX = ldq_phys(sm_state + 0x7ff0);
+    EDX = ldq_phys(sm_state + 0x7fe8);
+    EBX = ldq_phys(sm_state + 0x7fe0);
+    ESP = ldq_phys(sm_state + 0x7fd8);
+    EBP = ldq_phys(sm_state + 0x7fd0);
+    ESI = ldq_phys(sm_state + 0x7fc8);
+    EDI = ldq_phys(sm_state + 0x7fc0);
+    for(i = 8; i < 16; i++) 
+        env->regs[i] = ldq_phys(sm_state + 0x7ff8 - i * 8);
+    env->eip = ldq_phys(sm_state + 0x7f78);
+    load_eflags(ldl_phys(sm_state + 0x7f70), 
+                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
+    env->dr[6] = ldl_phys(sm_state + 0x7f68);
+    env->dr[7] = ldl_phys(sm_state + 0x7f60);
+
+    cpu_x86_update_cr4(env, ldl_phys(sm_state + 0x7f48));
+    cpu_x86_update_cr3(env, ldl_phys(sm_state + 0x7f50));
+    cpu_x86_update_cr0(env, ldl_phys(sm_state + 0x7f58));
+
+    val = ldl_phys(sm_state + 0x7efc); /* revision ID */
+    if (val & 0x20000) {
+        env->smbase = ldl_phys(sm_state + 0x7f00) & ~0x7fff;
+    }
+#else
+    cpu_x86_update_cr0(env, ldl_phys(sm_state + 0x7ffc));
+    cpu_x86_update_cr3(env, ldl_phys(sm_state + 0x7ff8));
+    load_eflags(ldl_phys(sm_state + 0x7ff4), 
+                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
+    env->eip = ldl_phys(sm_state + 0x7ff0);
+    EDI = ldl_phys(sm_state + 0x7fec);
+    ESI = ldl_phys(sm_state + 0x7fe8);
+    EBP = ldl_phys(sm_state + 0x7fe4);
+    ESP = ldl_phys(sm_state + 0x7fe0);
+    EBX = ldl_phys(sm_state + 0x7fdc);
+    EDX = ldl_phys(sm_state + 0x7fd8);
+    ECX = ldl_phys(sm_state + 0x7fd4);
+    EAX = ldl_phys(sm_state + 0x7fd0);
+    env->dr[6] = ldl_phys(sm_state + 0x7fcc);
+    env->dr[7] = ldl_phys(sm_state + 0x7fc8);
+    
+    env->tr.selector = ldl_phys(sm_state + 0x7fc4) & 0xffff;
+    env->tr.base = ldl_phys(sm_state + 0x7f64);
+    env->tr.limit = ldl_phys(sm_state + 0x7f60);
+    env->tr.flags = (ldl_phys(sm_state + 0x7f5c) & 0xf0ff) << 8;
+    
+    env->ldt.selector = ldl_phys(sm_state + 0x7fc0) & 0xffff;
+    env->ldt.base = ldl_phys(sm_state + 0x7f80);
+    env->ldt.limit = ldl_phys(sm_state + 0x7f7c);
+    env->ldt.flags = (ldl_phys(sm_state + 0x7f78) & 0xf0ff) << 8;
+    
+    env->gdt.base = ldl_phys(sm_state + 0x7f74);
+    env->gdt.limit = ldl_phys(sm_state + 0x7f70);
+
+    env->idt.base = ldl_phys(sm_state + 0x7f58);
+    env->idt.limit = ldl_phys(sm_state + 0x7f54);
+
+    for(i = 0; i < 6; i++) {
+        if (i < 3)
+            offset = 0x7f84 + i * 12;
+        else
+            offset = 0x7f2c + (i - 3) * 12;
+        cpu_x86_load_seg_cache(env, i, 
+                               ldl_phys(sm_state + 0x7fa8 + i * 4) & 0xffff,
+                               ldl_phys(sm_state + offset + 8),
+                               ldl_phys(sm_state + offset + 4),
+                               (ldl_phys(sm_state + offset) & 0xf0ff) << 8);
+    }
+    cpu_x86_update_cr4(env, ldl_phys(sm_state + 0x7f14));
+
+    val = ldl_phys(sm_state + 0x7efc); /* revision ID */
+    if (val & 0x20000) {
+        env->smbase = ldl_phys(sm_state + 0x7ef8) & ~0x7fff;
+    }
+#endif
+    CC_OP = CC_OP_EFLAGS;
+    env->hflags &= ~HF_SMM_MASK;
+    cpu_smm_update(env);
+
+    if (loglevel & CPU_LOG_INT) {
+        fprintf(logfile, "SMM: after RSM\n");
+        cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
+    }
+}
+
+#endif /* !CONFIG_USER_ONLY */
+
+
 #ifdef BUGGY_GCC_DIV64
 /* gcc 2.95.4 on PowerPC does not seem to like using __udivdi3, so we
    call it from another function */
@@ -1732,7 +2030,7 @@ void helper_lcall_real_T0_T1(int shift, int next_eip)
         PUSHW(ssp, esp, esp_mask, next_eip);
     }
 
-    ESP = (ESP & ~esp_mask) | (esp & esp_mask);
+    SET_ESP(esp, esp_mask);
     env->eip = new_eip;
     env->segs[R_CS].selector = new_cs;
     env->segs[R_CS].base = (new_cs << 4);
@@ -1818,7 +2116,7 @@ void helper_lcall_protected_T0_T1(int shift, int next_eip_addend)
             if (new_eip > limit)
                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
             /* from this point, not restartable */
-            ESP = (ESP & ~sp_mask) | (sp & sp_mask);
+            SET_ESP(sp, sp_mask);
             cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
                                    get_seg_base(e1, e2), limit, e2);
             EIP = new_eip;
@@ -1947,7 +2245,7 @@ void helper_lcall_protected_T0_T1(int shift, int next_eip_addend)
                        get_seg_limit(e1, e2),
                        e2);
         cpu_x86_set_cpl(env, dpl);
-        ESP = (ESP & ~sp_mask) | (sp & sp_mask);
+        SET_ESP(sp, sp_mask);
         EIP = offset;
     }
 #ifdef USE_KQEMU
@@ -2124,12 +2422,14 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend)
         if ((new_ss & 0xfffc) == 0) {
 #ifdef TARGET_X86_64
             /* NULL ss is allowed in long mode if cpl != 3*/
+            /* XXX: test CS64 ? */
             if ((env->hflags & HF_LMA_MASK) && rpl != 3) {
                 cpu_x86_load_seg_cache(env, R_SS, new_ss, 
                                        0, 0xffffffff,
                                        DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
                                        DESC_S_MASK | (rpl << DESC_DPL_SHIFT) |
                                        DESC_W_MASK | DESC_A_MASK);
+                ss_e2 = DESC_B_MASK; /* XXX: should not be needed ? */
             } else 
 #endif
             {
@@ -2176,7 +2476,7 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend)
 
         sp += addend;
     }
-    ESP = (ESP & ~sp_mask) | (sp & sp_mask);
+    SET_ESP(sp, sp_mask);
     env->eip = new_eip;
     if (is_iret) {
         /* NOTE: 'cpl' is the _old_ CPL */
@@ -3418,14 +3718,14 @@ void helper_hlt(void)
 
 void helper_monitor(void)
 {
-    if (ECX != 0)
+    if ((uint32_t)ECX != 0)
         raise_exception(EXCP0D_GPF);
     /* XXX: store address ? */
 }
 
 void helper_mwait(void)
 {
-    if (ECX != 0)
+    if ((uint32_t)ECX != 0)
         raise_exception(EXCP0D_GPF);
     /* XXX: not complete but not completely erroneous */
     if (env->cpu_index != 0 || env->next_cpu != NULL) {
index 19af159f9240565ea6472e4ab139be40bc808bbf..dc6a5000ecf66e2bf036681bbca62a5bf2e60814 100644 (file)
@@ -135,6 +135,8 @@ CPUX86State *cpu_x86_init(void)
 
         /* these features are needed for Win64 and aren't fully implemented */
         env->cpuid_features |= CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA;
+        /* this feature is needed for Solaris and isn't fully implemented */
+        env->cpuid_features |= CPUID_PSE36;
 #endif
     }
     cpu_reset(env);
@@ -161,7 +163,8 @@ void cpu_reset(CPUX86State *env)
 
     cpu_x86_update_cr0(env, 0x60000010);
     env->a20_mask = 0xffffffff;
-    
+    env->smbase = 0x30000;
+
     env->idt.limit = 0xffff;
     env->gdt.limit = 0xffff;
     env->ldt.limit = 0xffff;
@@ -268,7 +271,7 @@ void cpu_dump_state(CPUState *env, FILE *f,
                     "RSI=%016" PRIx64 " RDI=%016" PRIx64 " RBP=%016" PRIx64 " RSP=%016" PRIx64 "\n"
                     "R8 =%016" PRIx64 " R9 =%016" PRIx64 " R10=%016" PRIx64 " R11=%016" PRIx64 "\n"
                     "R12=%016" PRIx64 " R13=%016" PRIx64 " R14=%016" PRIx64 " R15=%016" PRIx64 "\n"
-                    "RIP=%016" PRIx64 " RFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d HLT=%d\n",
+                    "RIP=%016" PRIx64 " RFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
                     env->regs[R_EAX], 
                     env->regs[R_EBX], 
                     env->regs[R_ECX], 
@@ -296,13 +299,14 @@ void cpu_dump_state(CPUState *env, FILE *f,
                     env->hflags & HF_CPL_MASK, 
                     (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
                     (env->a20_mask >> 20) & 1,
+                    (env->hflags >> HF_SMM_SHIFT) & 1,
                     (env->hflags >> HF_HALTED_SHIFT) & 1);
     } else 
 #endif
     {
         cpu_fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
                     "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
-                    "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d HLT=%d\n",
+                    "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
                     (uint32_t)env->regs[R_EAX], 
                     (uint32_t)env->regs[R_EBX], 
                     (uint32_t)env->regs[R_ECX], 
@@ -322,6 +326,7 @@ void cpu_dump_state(CPUState *env, FILE *f,
                     env->hflags & HF_CPL_MASK, 
                     (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
                     (env->a20_mask >> 20) & 1,
+                    (env->hflags >> HF_SMM_SHIFT) & 1,
                     (env->hflags >> HF_HALTED_SHIFT) & 1);
     }
 
index 7a3aa77273002a71c52493dedf0616d9a897aaa4..a8cfce271b53869f9db104a1598a72624e5cb252 100644 (file)
@@ -678,6 +678,11 @@ void OPPROTO op_reset_inhibit_irq(void)
     env->hflags &= ~HF_INHIBIT_IRQ_MASK;
 }
 
+void OPPROTO op_rsm(void)
+{
+    helper_rsm();
+}
+
 #if 0
 /* vm86plus instructions */
 void OPPROTO op_cli_vm(void)
@@ -783,7 +788,7 @@ void OPPROTO op_movzwl_T0_T0(void)
 
 void OPPROTO op_movswl_EAX_AX(void)
 {
-    EAX = (int16_t)EAX;
+    EAX = (uint32_t)((int16_t)EAX);
 }
 
 #ifdef TARGET_X86_64
@@ -805,7 +810,7 @@ void OPPROTO op_movsbw_AX_AL(void)
 
 void OPPROTO op_movslq_EDX_EAX(void)
 {
-    EDX = (int32_t)EAX >> 31;
+    EDX = (uint32_t)((int32_t)EAX >> 31);
 }
 
 void OPPROTO op_movswl_DX_AX(void)
index cdc38012003223355a47663a19e7bc10c53b5928..df1527c554c5f97ccb47f2ced36cfc97216dac4d 100644 (file)
@@ -558,6 +558,25 @@ void OPPROTO glue(op_movl_T0_mm, SUFFIX) (void)
     T0 = s->L(0);
 }
 
+#ifdef TARGET_X86_64
+void OPPROTO glue(op_movq_mm_T0, SUFFIX) (void)
+{
+    Reg *d;
+    d = (Reg *)((char *)env + PARAM1);
+    d->Q(0) = T0;
+#if SHIFT == 1
+    d->Q(1) = 0;
+#endif
+}
+
+void OPPROTO glue(op_movq_T0_mm, SUFFIX) (void)
+{
+    Reg *s;
+    s = (Reg *)((char *)env + PARAM1);
+    T0 = s->Q(0);
+}
+#endif
+
 #if SHIFT == 0
 void OPPROTO glue(op_pshufw, SUFFIX) (void)
 {
index f905f323dd6a34dc03f5286af6b8ac2578825488..735acb0e47d7c37afa22556cb649e85358ae82ad 100644 (file)
@@ -1615,6 +1615,56 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_
     *offset_ptr = disp;
 }
 
+static void gen_nop_modrm(DisasContext *s, int modrm)
+{
+    int mod, rm, base, code;
+
+    mod = (modrm >> 6) & 3;
+    if (mod == 3)
+        return;
+    rm = modrm & 7;
+
+    if (s->aflag) {
+
+        base = rm;
+        
+        if (base == 4) {
+            code = ldub_code(s->pc++);
+            base = (code & 7);
+        }
+        
+        switch (mod) {
+        case 0:
+            if (base == 5) {
+                s->pc += 4;
+            }
+            break;
+        case 1:
+            s->pc++;
+            break;
+        default:
+        case 2:
+            s->pc += 4;
+            break;
+        }
+    } else {
+        switch (mod) {
+        case 0:
+            if (rm == 6) {
+                s->pc += 2;
+            }
+            break;
+        case 1:
+            s->pc++;
+            break;
+        default:
+        case 2:
+            s->pc += 2;
+            break;
+        }
+    }
+}
+
 /* used for LEA and MOV AX, mem */
 static void gen_add_A0_ds_seg(DisasContext *s)
 {
@@ -2571,12 +2621,28 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
             gen_sto_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg]));
             break;
         case 0x6e: /* movd mm, ea */
-            gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 0);
-            gen_op_movl_mm_T0_mmx(offsetof(CPUX86State,fpregs[reg].mmx));
+#ifdef TARGET_X86_64
+            if (s->dflag == 2) {
+                gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 0);
+                gen_op_movq_mm_T0_mmx(offsetof(CPUX86State,fpregs[reg].mmx));
+            } else 
+#endif
+            {
+                gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 0);
+                gen_op_movl_mm_T0_mmx(offsetof(CPUX86State,fpregs[reg].mmx));
+            }
             break;
         case 0x16e: /* movd xmm, ea */
-            gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 0);
-            gen_op_movl_mm_T0_xmm(offsetof(CPUX86State,xmm_regs[reg]));
+#ifdef TARGET_X86_64
+            if (s->dflag == 2) {
+                gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 0);
+                gen_op_movq_mm_T0_xmm(offsetof(CPUX86State,xmm_regs[reg]));
+            } else 
+#endif
+            {
+                gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 0);
+                gen_op_movl_mm_T0_xmm(offsetof(CPUX86State,xmm_regs[reg]));
+            }
             break;
         case 0x6f: /* movq mm, ea */
             if (mod != 3) {
@@ -2700,12 +2766,28 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
                         offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
             break;
         case 0x7e: /* movd ea, mm */
-            gen_op_movl_T0_mm_mmx(offsetof(CPUX86State,fpregs[reg].mmx));
-            gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 1);
+#ifdef TARGET_X86_64
+            if (s->dflag == 2) {
+                gen_op_movq_T0_mm_mmx(offsetof(CPUX86State,fpregs[reg].mmx));
+                gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 1);
+            } else 
+#endif
+            {
+                gen_op_movl_T0_mm_mmx(offsetof(CPUX86State,fpregs[reg].mmx));
+                gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 1);
+            }
             break;
         case 0x17e: /* movd ea, xmm */
-            gen_op_movl_T0_mm_xmm(offsetof(CPUX86State,xmm_regs[reg]));
-            gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 1);
+#ifdef TARGET_X86_64
+            if (s->dflag == 2) {
+                gen_op_movq_T0_mm_xmm(offsetof(CPUX86State,xmm_regs[reg]));
+                gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 1);
+            } else 
+#endif
+            {
+                gen_op_movl_T0_mm_xmm(offsetof(CPUX86State,xmm_regs[reg]));
+                gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 1);
+            }
             break;
         case 0x27e: /* movq xmm, ea */
             if (mod != 3) {
@@ -5791,10 +5873,15 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
             /* nothing more to do */
             break;
-        default:
-            goto illegal_op;
+        default: /* nop (multi byte) */
+            gen_nop_modrm(s, modrm);
+            break;
         }
         break;
+    case 0x119 ... 0x11f: /* nop (multi byte) */
+        modrm = ldub_code(s->pc++);
+        gen_nop_modrm(s, modrm);
+        break;
     case 0x120: /* mov reg, crN */
     case 0x122: /* mov crN, reg */
         if (s->cpl != 0) {
@@ -5957,6 +6044,17 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
         gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
         /* ignore for now */
         break;
+    case 0x1aa: /* rsm */
+        if (!(s->flags & HF_SMM_MASK))
+            goto illegal_op;
+        if (s->cc_op != CC_OP_DYNAMIC) {
+            gen_op_set_cc_op(s->cc_op);
+            s->cc_op = CC_OP_DYNAMIC;
+        }
+        gen_jmp_im(s->pc - s->cs_base);
+        gen_op_rsm();
+        gen_eob(s);
+        break;
     case 0x110 ... 0x117:
     case 0x128 ... 0x12f:
     case 0x150 ... 0x177:
index abafbef7803519264b386570442a94ad3b2273e6..791a84dc771fdde61ff71f88b4d39b8b06127d4c 100644 (file)
@@ -1,18 +1,19 @@
-/.cvsignore/1.4/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
-/Makefile/1.37/Sun Aug  6 01:04:06 2006//Trelease_0_8_2
-/hello-arm.c/1.1/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
-/hello-i386.c/1.1/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
-/linux-test.c/1.3/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
-/pi_10.com/1.1/Sun Aug  6 01:04:06 2006/-kb/Trelease_0_8_2
-/qruncom.c/1.4/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
-/runcom.c/1.3/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
-/sha1.c/1.1/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
-/test-i386-code16.S/1.3/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
-/test-i386-muldiv.h/1.2/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
-/test-i386-shift.h/1.5/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
-/test-i386-vm86.S/1.1/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
-/test-i386.c/1.52/Sun Aug  6 01:04:06 2006//Trelease_0_8_2
-/test-i386.h/1.2/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
-/test_path.c/1.1/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
-/testthread.c/1.2/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
+/.cvsignore/1.4/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/Makefile/1.40/Thu May  3 17:18:16 2007//Trelease_0_9_0
+/hello-arm.c/1.1/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/hello-i386.c/1.1/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/hello-mips.c/1.1/Thu Dec 14 14:48:11 2006//Trelease_0_9_0
+/linux-test.c/1.3/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/pi_10.com/1.1/Thu May  3 17:18:16 2007/-kb/Trelease_0_9_0
+/qruncom.c/1.4/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/runcom.c/1.3/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/sha1.c/1.1/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/test-i386-code16.S/1.3/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/test-i386-muldiv.h/1.2/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/test-i386-shift.h/1.5/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/test-i386-vm86.S/1.1/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/test-i386.c/1.53/Thu May  3 17:18:16 2007//Trelease_0_9_0
+/test-i386.h/1.2/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/test_path.c/1.1/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
+/testthread.c/1.2/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
 D
index bd48d406fa1b16a1721b34dc4bb6979acc4274da..eed9f4a4fb93e992c8c20b591822041f09711c7e 100644 (file)
@@ -1 +1 @@
-Nrelease_0_8_2
+Nrelease_0_9_0
index d7abae69e39df28f86869c6fee5a8493509101e1..79a3d55b5d74eca5378fb8822764eb57e4f37566 100644 (file)
@@ -13,7 +13,7 @@ endif
 TESTS+=sha1# test_path
 #TESTS+=test_path
 
-QEMU=../i386-user/qemu-i386
+QEMU=../i386-linux-user/qemu-i386
 
 all: $(TESTS)
 
@@ -82,10 +82,17 @@ hello-arm: hello-arm.o
 hello-arm.o: hello-arm.c
        arm-linux-gcc -Wall -g -O2 -c -o $@ $<
 
+# MIPS test
+hello-mips: hello-mips.c
+       mips-linux-gnu-gcc -nostdlib -static -mno-abicalls -fno-PIC -mabi=32 -Wall -Wextra -g -O2 -o $@ $<
+
+hello-mipsel: hello-mips.c
+       mipsel-linux-gnu-gcc -nostdlib -static -mno-abicalls -fno-PIC -mabi=32 -Wall -Wextra -g -O2 -o $@ $<
+
 # XXX: find a way to compile easily a test for each arch
 test2:
        @for arch in i386 arm armeb sparc ppc mips mipsel; do \
-           ../$${arch}-user/qemu-$${arch} $${arch}/ls -l linux-test.c ; \
+           ../$${arch}-linux-user/qemu-$${arch} $${arch}/ls -l linux-test.c ; \
         done
 
 clean:
diff --git a/tools/ioemu/tests/hello-mips.c b/tools/ioemu/tests/hello-mips.c
new file mode 100644 (file)
index 0000000..f825673
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+* MIPS o32 Linux syscall example
+*
+* http://www.linux-mips.org/wiki/RISC/os
+* http://www.linux-mips.org/wiki/MIPSABIHistory
+* http://www.linux.com/howtos/Assembly-HOWTO/mips.shtml
+*
+* mipsel-linux-gcc -nostdlib -mno-abicalls -fno-PIC -mabi=32 \
+*                  -O2 -static -o hello-mips hello-mips.c
+*
+*/
+#define __NR_SYSCALL_BASE      4000
+#define __NR_exit                      (__NR_SYSCALL_BASE+  1)
+#define __NR_write                     (__NR_SYSCALL_BASE+  4)
+
+static inline void exit1(int status)
+{
+    register unsigned long __a0 asm("$4") = (unsigned long) status;
+
+    __asm__ __volatile__ (
+        "      .set push       \n"
+        "      .set noreorder  \n"
+        "      li      $2, %0  \n"
+        "      syscall         \n"
+        "      .set pop        "
+        :
+       : "i" (__NR_exit), "r" (__a0)
+       : "$2", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24",
+         "memory");
+}
+
+static inline int write(int fd, const char *buf, int len)
+{
+    register unsigned long __a0 asm("$4") = (unsigned long) fd;
+    register unsigned long __a1 asm("$5") = (unsigned long) buf;
+    register unsigned long __a2 asm("$6") = (unsigned long) len;
+    register unsigned long __a3 asm("$7");
+    unsigned long __v0;
+
+    __asm__ __volatile__ (
+        "      .set push       \n"
+        "      .set noreorder  \n"
+        "      li      $2, %2  \n"
+        "      syscall         \n"
+        "      move    %0, $2  \n"
+        "      .set pop        "
+        : "=r" (__v0), "=r" (__a3)
+        : "i" (__NR_write), "r" (__a0), "r" (__a1), "r" (__a2)
+       : "$2", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24",
+         "memory");
+
+/*    if (__a3 == 0) */
+        return (int) __v0;
+/*
+    errno = __v0;
+    return -1;
+ */
+}
+
+void __start(void)
+{
+    write (1, "Hello, World!\n", 14);
+    exit1 (42);
+}
index 4a25d03b6662d0552daed4589485cc58a0350e8a..267391575a445ae3307c0f183ce1d3f518601754 100644 (file)
@@ -2583,6 +2583,41 @@ void test_sse(void)
 
 #endif
 
+#define TEST_CONV_RAX(op)\
+{\
+    unsigned long a, r;\
+    a = i2l(0x8234a6f8);\
+    r = a;\
+    asm volatile(#op : "=a" (r) : "0" (r));\
+    printf("%-10s A=" FMTLX " R=" FMTLX "\n", #op, a, r);\
+}
+
+#define TEST_CONV_RAX_RDX(op)\
+{\
+    unsigned long a, d, r, rh;                   \
+    a = i2l(0x8234a6f8);\
+    d = i2l(0x8345a1f2);\
+    r = a;\
+    rh = d;\
+    asm volatile(#op : "=a" (r), "=d" (rh) : "0" (r), "1" (rh));   \
+    printf("%-10s A=" FMTLX " R=" FMTLX ":" FMTLX "\n", #op, a, r, rh);  \
+}
+
+void test_conv(void)
+{
+    TEST_CONV_RAX(cbw);
+    TEST_CONV_RAX(cwde);
+#if defined(__x86_64__)
+    TEST_CONV_RAX(cdqe);
+#endif
+
+    TEST_CONV_RAX_RDX(cwd);
+    TEST_CONV_RAX_RDX(cdq);
+#if defined(__x86_64__)
+    TEST_CONV_RAX_RDX(cqo);
+#endif
+}
+
 extern void *__start_initcall;
 extern void *__stop_initcall;
 
@@ -2621,6 +2656,7 @@ int main(int argc, char **argv)
     test_single_step();
 #endif
     test_enter();
+    test_conv();
 #ifdef TEST_SSE
     test_sse();
     test_fxsave();
index 0de429f5b9ed3db4b56e35637808cc075e7949ed..43365478bdef14fb3ff5d22b89e26fb54512f07f 100644 (file)
@@ -302,6 +302,8 @@ int cpu_restore_state(TranslationBlock *tb,
         }
         env->access_type = type;
     }
+#elif defined(TARGET_M68K)
+    env->pc = gen_opc_pc[j];
 #elif defined(TARGET_MIPS)
     env->PC = gen_opc_pc[j];
     env->hflags &= ~MIPS_HFLAG_BMASK;
index ef601797041a89388bddd29340c647a79d072d68..d0a75d8cdc5608060ce76d12ca88e3b7adc7ff5c 100644 (file)
@@ -116,22 +116,21 @@ static int usb_host_handle_control(USBDevice *dev,
    }
 }
 
-static int usb_host_handle_data(USBDevice *dev, int pid, 
-                                uint8_t devep,
-                                uint8_t *data, int len)
+static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
 {
     USBHostDevice *s = (USBHostDevice *)dev;
     struct usbdevfs_bulktransfer bt;
     int ret;
+    uint8_t devep = p->devep;
 
     /* XXX: optimize and handle all data types by looking at the
        config descriptor */
-    if (pid == USB_TOKEN_IN)
+    if (p->pid == USB_TOKEN_IN)
         devep |= 0x80;
     bt.ep = devep;
-    bt.len = len;
+    bt.len = p->len;
     bt.timeout = 50;
-    bt.data = data;
+    bt.data = p->data;
     ret = ioctl(s->fd, USBDEVFS_BULK, &bt);
     if (ret < 0) {
         switch(errno) {
index 6f5d34a9926e8e9a30a897814924e0fdb6105427..e71001262cb91656ea2716ed1d3f298d3d3a63ea 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * QEMU System Emulator
  * 
- * Copyright (c) 2003-2005 Fabrice Bellard
+ * Copyright (c) 2003-2007 Fabrice Bellard
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -29,6 +29,7 @@
 #include <time.h>
 #include <errno.h>
 #include <sys/time.h>
+#include <zlib.h>
 
 #ifndef _WIN32
 #include <sys/times.h>
 #include <xen/hvm/params.h>
 #define DEFAULT_NETWORK_SCRIPT "/etc/xen/qemu-ifup"
 #define DEFAULT_BRIDGE "xenbr0"
+#ifdef __sun__
+#define SMBD_COMMAND "/usr/sfw/sbin/smbd"
+#else
+#define SMBD_COMMAND "/usr/sbin/smbd"
+#endif
 
 //#define DEBUG_UNUSED_IOPORT
 //#define DEBUG_IOPORT
@@ -116,7 +122,11 @@ char phys_ram_file[1024];
 void *ioport_opaque[MAX_IOPORTS];
 IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS];
 IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS];
-BlockDriverState *bs_table[MAX_DISKS + MAX_SCSI_DISKS], *fd_table[MAX_FD];
+/* Note: bs_table[MAX_DISKS] is a dummy block driver if none available
+   to store the VM snapshots */
+BlockDriverState *bs_table[MAX_DISKS + MAX_SCSI_DISKS + 1], *fd_table[MAX_FD];
+/* point to the block driver where the snapshots are managed */
+BlockDriverState *bs_snapshots;
 int vga_ram_size;
 int bios_size;
 static DisplayState display_state;
@@ -144,6 +154,7 @@ int graphic_height = 600;
 #endif
 int graphic_depth = 15;
 int full_screen = 0;
+int no_quit = 0;
 CharDriverState *serial_hds[MAX_SERIAL_PORTS];
 CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
 #ifdef TARGET_I386
@@ -152,7 +163,7 @@ int win2k_install_hack = 0;
 int usb_enabled = 0;
 static VLANState *first_vlan;
 int smp_cpus = 1;
-int vnc_display = -1;
+const char *vnc_display;
 #if defined(TARGET_SPARC)
 #define MAX_CPUS 16
 #elif defined(TARGET_I386)
@@ -162,6 +173,12 @@ int vnc_display = -1;
 #endif
 int acpi_enabled = 0;
 int fd_bootchk = 1;
+int no_reboot = 0;
+int daemonize = 0;
+const char *option_rom[MAX_OPTION_ROMS];
+int nb_option_roms;
+int semihosting_enabled = 0;
+int autostart = 1;
 
 extern int vcpus;
 
@@ -261,7 +278,7 @@ int register_ioport_read(int start, int length, int size,
     for(i = start; i < start + length; i += size) {
         ioport_read_table[bsize][i] = func;
         if (ioport_opaque[i] != NULL && ioport_opaque[i] != opaque)
-            hw_error("register_ioport_read: invalid opaque");
+            hw_error("register_ioport_write: invalid opaque");
         ioport_opaque[i] = opaque;
     }
     return 0;
@@ -309,49 +326,6 @@ void isa_unassign_ioport(int start, int length)
 
 /***********************************************************/
 
-void pstrcpy(char *buf, int buf_size, const char *str)
-{
-    int c;
-    char *q = buf;
-
-    if (buf_size <= 0)
-        return;
-
-    for(;;) {
-        c = *str++;
-        if (c == 0 || q >= buf + buf_size - 1)
-            break;
-        *q++ = c;
-    }
-    *q = '\0';
-}
-
-/* strcat and truncate. */
-char *pstrcat(char *buf, int buf_size, const char *s)
-{
-    int len;
-    len = strlen(buf);
-    if (len < buf_size) 
-        pstrcpy(buf + len, buf_size - len, s);
-    return buf;
-}
-
-int strstart(const char *str, const char *val, const char **ptr)
-{
-    const char *p, *q;
-    p = str;
-    q = val;
-    while (*q != '\0') {
-        if (*p != *q)
-            return 0;
-        p++;
-        q++;
-    }
-    if (ptr)
-        *ptr = p;
-    return 1;
-}
-
 void cpu_outb(CPUState *env, int addr, int val)
 {
 #ifdef DEBUG_IOPORT
@@ -467,9 +441,8 @@ void hw_error(const char *fmt, ...)
 
 static QEMUPutKBDEvent *qemu_put_kbd_event;
 static void *qemu_put_kbd_event_opaque;
-static QEMUPutMouseEvent *qemu_put_mouse_event;
-static void *qemu_put_mouse_event_opaque;
-static int qemu_put_mouse_event_absolute;
+static QEMUPutMouseEntry *qemu_put_mouse_event_head;
+static QEMUPutMouseEntry *qemu_put_mouse_event_current;
 
 void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
 {
@@ -477,11 +450,68 @@ void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
     qemu_put_kbd_event = func;
 }
 
-void qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, void *opaque, int absolute)
+QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func,
+                                                void *opaque, int absolute,
+                                                const char *name)
+{
+    QEMUPutMouseEntry *s, *cursor;
+
+    s = qemu_mallocz(sizeof(QEMUPutMouseEntry));
+    if (!s)
+        return NULL;
+
+    s->qemu_put_mouse_event = func;
+    s->qemu_put_mouse_event_opaque = opaque;
+    s->qemu_put_mouse_event_absolute = absolute;
+    s->qemu_put_mouse_event_name = qemu_strdup(name);
+    s->next = NULL;
+
+    if (!qemu_put_mouse_event_head) {
+        qemu_put_mouse_event_head = qemu_put_mouse_event_current = s;
+        return s;
+    }
+
+    cursor = qemu_put_mouse_event_head;
+    while (cursor->next != NULL)
+        cursor = cursor->next;
+
+    cursor->next = s;
+    qemu_put_mouse_event_current = s;
+
+    return s;
+}
+
+void qemu_remove_mouse_event_handler(QEMUPutMouseEntry *entry)
 {
-    qemu_put_mouse_event_opaque = opaque;
-    qemu_put_mouse_event = func;
-    qemu_put_mouse_event_absolute = absolute;
+    QEMUPutMouseEntry *prev = NULL, *cursor;
+
+    if (!qemu_put_mouse_event_head || entry == NULL)
+        return;
+
+    cursor = qemu_put_mouse_event_head;
+    while (cursor != NULL && cursor != entry) {
+        prev = cursor;
+        cursor = cursor->next;
+    }
+
+    if (cursor == NULL) // does not exist or list empty
+        return;
+    else if (prev == NULL) { // entry is head
+        qemu_put_mouse_event_head = cursor->next;
+        if (qemu_put_mouse_event_current == entry)
+            qemu_put_mouse_event_current = cursor->next;
+        qemu_free(entry->qemu_put_mouse_event_name);
+        qemu_free(entry);
+        return;
+    }
+
+    prev->next = entry->next;
+
+    if (qemu_put_mouse_event_current == entry)
+        qemu_put_mouse_event_current = prev;
+
+    qemu_free(entry->qemu_put_mouse_event_name);
+    qemu_free(entry);
 }
 
 void kbd_put_keycode(int keycode)
@@ -493,15 +523,72 @@ void kbd_put_keycode(int keycode)
 
 void kbd_mouse_event(int dx, int dy, int dz, int buttons_state)
 {
-    if (qemu_put_mouse_event) {
-        qemu_put_mouse_event(qemu_put_mouse_event_opaque, 
-                             dx, dy, dz, buttons_state);
+    QEMUPutMouseEvent *mouse_event;
+    void *mouse_event_opaque;
+
+    if (!qemu_put_mouse_event_current) {
+        return;
+    }
+
+    mouse_event =
+        qemu_put_mouse_event_current->qemu_put_mouse_event;
+    mouse_event_opaque =
+        qemu_put_mouse_event_current->qemu_put_mouse_event_opaque;
+
+    if (mouse_event) {
+        mouse_event(mouse_event_opaque, dx, dy, dz, buttons_state);
     }
 }
 
 int kbd_mouse_is_absolute(void)
 {
-    return qemu_put_mouse_event_absolute;
+    if (!qemu_put_mouse_event_current)
+        return 0;
+
+    return qemu_put_mouse_event_current->qemu_put_mouse_event_absolute;
+}
+
+void do_info_mice(void)
+{
+    QEMUPutMouseEntry *cursor;
+    int index = 0;
+
+    if (!qemu_put_mouse_event_head) {
+        term_printf("No mouse devices connected\n");
+        return;
+    }
+
+    term_printf("Mouse devices available:\n");
+    cursor = qemu_put_mouse_event_head;
+    while (cursor != NULL) {
+        term_printf("%c Mouse #%d: %s\n",
+                    (cursor == qemu_put_mouse_event_current ? '*' : ' '),
+                    index, cursor->qemu_put_mouse_event_name);
+        index++;
+        cursor = cursor->next;
+    }
+}
+
+void do_mouse_set(int index)
+{
+    QEMUPutMouseEntry *cursor;
+    int i = 0;
+
+    if (!qemu_put_mouse_event_head) {
+        term_printf("No mouse devices connected\n");
+        return;
+    }
+
+    cursor = qemu_put_mouse_event_head;
+    while (cursor != NULL && index != i) {
+        i++;
+        cursor = cursor->next;
+    }
+
+    if (cursor != NULL)
+        qemu_put_mouse_event_current = cursor;
+    else
+        term_printf("Mouse at given index not found\n");
 }
 
 /* compute with 96 bit intermediate result: (a*b)/c */
@@ -868,17 +955,21 @@ static void timer_save(QEMUFile *f, void *opaque)
     }
     qemu_put_be64s(f, &cpu_ticks_offset);
     qemu_put_be64s(f, &ticks_per_sec);
+    qemu_put_be64s(f, &cpu_clock_offset);
 }
 
 static int timer_load(QEMUFile *f, void *opaque, int version_id)
 {
-    if (version_id != 1)
+    if (version_id != 1 && version_id != 2)
         return -EINVAL;
     if (cpu_ticks_enabled) {
         return -EINVAL;
     }
     qemu_get_be64s(f, &cpu_ticks_offset);
     qemu_get_be64s(f, &ticks_per_sec);
+    if (version_id == 2) {
+        qemu_get_be64s(f, &cpu_clock_offset);
+    }
     return 0;
 }
 
@@ -1084,6 +1175,29 @@ void quit_timers(void)
 /***********************************************************/
 /* character device */
 
+static void qemu_chr_event(CharDriverState *s, int event)
+{
+    if (!s->chr_event)
+        return;
+    s->chr_event(s->handler_opaque, event);
+}
+
+static void qemu_chr_reset_bh(void *opaque)
+{
+    CharDriverState *s = opaque;
+    qemu_chr_event(s, CHR_EVENT_RESET);
+    qemu_bh_delete(s->bh);
+    s->bh = NULL;
+}
+
+void qemu_chr_reset(CharDriverState *s)
+{
+    if (s->bh == NULL) {
+       s->bh = qemu_bh_new(qemu_chr_reset_bh, s);
+       qemu_bh_schedule(s->bh);
+    }
+}
+
 int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len)
 {
     return s->chr_write(s, buf, len);
@@ -1096,6 +1210,19 @@ int qemu_chr_ioctl(CharDriverState *s, int cmd, void *arg)
     return s->chr_ioctl(s, cmd, arg);
 }
 
+int qemu_chr_can_read(CharDriverState *s)
+{
+    if (!s->chr_can_read)
+        return 0;
+    return s->chr_can_read(s->handler_opaque);
+}
+
+void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len)
+{
+    s->chr_read(s->handler_opaque, buf, len);
+}
+
+
 void qemu_chr_printf(CharDriverState *s, const char *fmt, ...)
 {
     char buf[4096];
@@ -1112,30 +1239,26 @@ void qemu_chr_send_event(CharDriverState *s, int event)
         s->chr_send_event(s, event);
 }
 
-void qemu_chr_add_read_handler(CharDriverState *s, 
-                               IOCanRWHandler *fd_can_read, 
-                               IOReadHandler *fd_read, void *opaque)
+void qemu_chr_add_handlers(CharDriverState *s, 
+                           IOCanRWHandler *fd_can_read, 
+                           IOReadHandler *fd_read,
+                           IOEventHandler *fd_event,
+                           void *opaque)
 {
-    s->chr_add_read_handler(s, fd_can_read, fd_read, opaque);
+    s->chr_can_read = fd_can_read;
+    s->chr_read = fd_read;
+    s->chr_event = fd_event;
+    s->handler_opaque = opaque;
+    if (s->chr_update_read_handler)
+        s->chr_update_read_handler(s);
 }
              
-void qemu_chr_add_event_handler(CharDriverState *s, IOEventHandler *chr_event)
-{
-    s->chr_event = chr_event;
-}
-
 static int null_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
 {
     return len;
 }
 
-static void null_chr_add_read_handler(CharDriverState *chr, 
-                                    IOCanRWHandler *fd_can_read, 
-                                    IOReadHandler *fd_read, void *opaque)
-{
-}
-
-CharDriverState *qemu_chr_open_null(void)
+static CharDriverState *qemu_chr_open_null(void)
 {
     CharDriverState *chr;
 
@@ -1143,7 +1266,6 @@ CharDriverState *qemu_chr_open_null(void)
     if (!chr)
         return NULL;
     chr->chr_write = null_chr_write;
-    chr->chr_add_read_handler = null_chr_add_read_handler;
     return chr;
 }
 
@@ -1250,9 +1372,6 @@ void socket_set_nonblock(int fd)
 
 typedef struct {
     int fd_in, fd_out;
-    IOCanRWHandler *fd_can_read; 
-    IOReadHandler *fd_read;
-    void *fd_opaque;
     int max_size;
 } FDCharDriver;
 
@@ -1272,7 +1391,7 @@ static int fd_chr_read_poll(void *opaque)
     CharDriverState *chr = opaque;
     FDCharDriver *s = chr->opaque;
 
-    s->max_size = s->fd_can_read(s->fd_opaque);
+    s->max_size = qemu_chr_can_read(chr);
     return s->max_size;
 }
 
@@ -1289,21 +1408,21 @@ static void fd_chr_read(void *opaque)
     if (len == 0)
         return;
     size = read(s->fd_in, buf, len);
+    if (size == 0) {
+        /* FD has been closed. Remove it from the active list.  */
+        qemu_set_fd_handler2(s->fd_in, NULL, NULL, NULL, NULL);
+        return;
+    }
     if (size > 0) {
-        s->fd_read(s->fd_opaque, buf, size);
+        qemu_chr_read(chr, buf, size);
     }
 }
 
-static void fd_chr_add_read_handler(CharDriverState *chr, 
-                                    IOCanRWHandler *fd_can_read, 
-                                    IOReadHandler *fd_read, void *opaque)
+static void fd_chr_update_read_handler(CharDriverState *chr)
 {
     FDCharDriver *s = chr->opaque;
 
     if (s->fd_in >= 0) {
-        s->fd_can_read = fd_can_read;
-        s->fd_read = fd_read;
-        s->fd_opaque = opaque;
         if (nographic && s->fd_in == 0) {
         } else {
             qemu_set_fd_handler2(s->fd_in, fd_chr_read_poll, 
@@ -1313,7 +1432,7 @@ static void fd_chr_add_read_handler(CharDriverState *chr,
 }
 
 /* open a character device to a unix fd */
-CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out)
+static CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out)
 {
     CharDriverState *chr;
     FDCharDriver *s;
@@ -1330,11 +1449,14 @@ CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out)
     s->fd_out = fd_out;
     chr->opaque = s;
     chr->chr_write = fd_chr_write;
-    chr->chr_add_read_handler = fd_chr_add_read_handler;
+    chr->chr_update_read_handler = fd_chr_update_read_handler;
+
+    qemu_chr_reset(chr);
+
     return chr;
 }
 
-CharDriverState *qemu_chr_open_file_out(const char *file_out)
+static CharDriverState *qemu_chr_open_file_out(const char *file_out)
 {
     int fd_out;
 
@@ -1344,14 +1466,25 @@ CharDriverState *qemu_chr_open_file_out(const char *file_out)
     return qemu_chr_open_fd(-1, fd_out);
 }
 
-CharDriverState *qemu_chr_open_pipe(const char *filename)
+static CharDriverState *qemu_chr_open_pipe(const char *filename)
 {
-    int fd;
-
-    fd = open(filename, O_RDWR | O_BINARY);
-    if (fd < 0)
-        return NULL;
-    return qemu_chr_open_fd(fd, fd);
+    int fd_in, fd_out;
+    char filename_in[256], filename_out[256];
+
+    snprintf(filename_in, 256, "%s.in", filename);
+    snprintf(filename_out, 256, "%s.out", filename);
+    fd_in = open(filename_in, O_RDWR | O_BINARY);
+    fd_out = open(filename_out, O_RDWR | O_BINARY);
+    if (fd_in < 0 || fd_out < 0) {
+       if (fd_in >= 0)
+           close(fd_in);
+       if (fd_out >= 0)
+           close(fd_out);
+        fd_in = fd_out = open(filename, O_RDWR | O_BINARY);
+        if (fd_in < 0)
+            return NULL;
+    }
+    return qemu_chr_open_fd(fd_in, fd_out);
 }
 
 
@@ -1409,7 +1542,7 @@ static void stdio_received_byte(int ch)
 
                 chr = stdio_clients[client_index];
                 s = chr->opaque;
-                chr->chr_event(s->fd_opaque, CHR_EVENT_BREAK);
+                qemu_chr_event(chr, CHR_EVENT_BREAK);
             }
             break;
         case 'c':
@@ -1436,13 +1569,11 @@ static void stdio_received_byte(int ch)
         if (client_index < stdio_nb_clients) {
             uint8_t buf[1];
             CharDriverState *chr;
-            FDCharDriver *s;
             
             chr = stdio_clients[client_index];
-            s = chr->opaque;
-            if (s->fd_can_read(s->fd_opaque) > 0) {
+            if (qemu_chr_can_read(chr) > 0) {
                 buf[0] = ch;
-                s->fd_read(s->fd_opaque, buf, 1);
+                qemu_chr_read(chr, buf, 1);
             } else if (term_fifo_size == 0) {
                 term_fifo[term_fifo_size++] = ch;
             }
@@ -1453,14 +1584,12 @@ static void stdio_received_byte(int ch)
 static int stdio_read_poll(void *opaque)
 {
     CharDriverState *chr;
-    FDCharDriver *s;
 
     if (client_index < stdio_nb_clients) {
         chr = stdio_clients[client_index];
-        s = chr->opaque;
         /* try to flush the queue if needed */
-        if (term_fifo_size != 0 && s->fd_can_read(s->fd_opaque) > 0) {
-            s->fd_read(s->fd_opaque, term_fifo, 1);
+        if (term_fifo_size != 0 && qemu_chr_can_read(chr) > 0) {
+            qemu_chr_read(chr, term_fifo, 1);
             term_fifo_size = 0;
         }
         /* see if we can absorb more chars */
@@ -1479,6 +1608,11 @@ static void stdio_read(void *opaque)
     uint8_t buf[1];
     
     size = read(0, buf, 1);
+    if (size == 0) {
+        /* stdin has been closed. Remove it from the active list.  */
+        qemu_set_fd_handler2(0, NULL, NULL, NULL, NULL);
+        return;
+    }
     if (size > 0)
         stdio_received_byte(buf[0]);
 }
@@ -1553,7 +1687,7 @@ static void term_init(void)
     fcntl(0, F_SETFL, O_NONBLOCK);
 }
 
-CharDriverState *qemu_chr_open_stdio(void)
+static CharDriverState *qemu_chr_open_stdio(void)
 {
     CharDriverState *chr;
 
@@ -1664,7 +1798,7 @@ static int store_dev_info(char *devName, int domid,
 }
 
 #if defined(__linux__)
-CharDriverState *qemu_chr_open_pty(void)
+static CharDriverState *qemu_chr_open_pty(void)
 {
     struct termios tty;
     int master_fd, slave_fd;
@@ -1742,7 +1876,7 @@ static void tty_serial_init(int fd, int speed,
                           |INLCR|IGNCR|ICRNL|IXON);
     tty.c_oflag &= ~OPOST; /* no output mangling of raw serial stream */
     tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN|ISIG);
-    tty.c_cflag &= ~(CSIZE|PARENB|PARODD|CRTSCTS);
+    tty.c_cflag &= ~(CSIZE|PARENB|PARODD|CRTSCTS|CSTOPB);
     switch(data_bits) {
     default:
     case 8:
@@ -1769,6 +1903,8 @@ static void tty_serial_init(int fd, int speed,
         tty.c_cflag |= PARENB | PARODD;
         break;
     }
+    if (stop_bits == 2)
+        tty.c_cflag |= CSTOPB;
     
     tcsetattr (fd, TCSANOW, &tty);
 }
@@ -1798,7 +1934,7 @@ static int tty_serial_ioctl(CharDriverState *chr, int cmd, void *arg)
     return 0;
 }
 
-CharDriverState *qemu_chr_open_tty(const char *filename)
+static CharDriverState *qemu_chr_open_tty(const char *filename)
 {
     CharDriverState *chr;
     int fd;
@@ -1812,6 +1948,7 @@ CharDriverState *qemu_chr_open_tty(const char *filename)
     if (!chr)
         return NULL;
     chr->chr_ioctl = tty_serial_ioctl;
+    qemu_chr_reset(chr);
     return chr;
 }
 
@@ -1852,7 +1989,7 @@ static int pp_ioctl(CharDriverState *chr, int cmd, void *arg)
     return 0;
 }
 
-CharDriverState *qemu_chr_open_pp(const char *filename)
+static CharDriverState *qemu_chr_open_pp(const char *filename)
 {
     CharDriverState *chr;
     int fd;
@@ -1873,13 +2010,15 @@ CharDriverState *qemu_chr_open_pp(const char *filename)
     }
     chr->opaque = (void *)fd;
     chr->chr_write = null_chr_write;
-    chr->chr_add_read_handler = null_chr_add_read_handler;
     chr->chr_ioctl = pp_ioctl;
+
+    qemu_chr_reset(chr);
+
     return chr;
 }
 
 #else
-CharDriverState *qemu_chr_open_pty(void)
+static CharDriverState *qemu_chr_open_pty(void)
 {
     return NULL;
 }
@@ -1889,9 +2028,7 @@ CharDriverState *qemu_chr_open_pty(void)
 
 #ifdef _WIN32
 typedef struct {
-    IOCanRWHandler *fd_can_read; 
-    IOReadHandler *fd_read;
-    void *win_opaque;
+    CharDriverState *chr;
     int max_size;
     HANDLE hcom, hrecv, hsend;
     OVERLAPPED orecv, osend;
@@ -1933,7 +2070,7 @@ static void win_chr_close(CharDriverState *chr)
     win_chr_close2(s);
 }
 
-static int win_chr_init(WinCharState *s, const char *filename)
+static int win_chr_init(WinCharState *s, CharDriverState *chr, const char *filename)
 {
     COMMCONFIG comcfg;
     COMMTIMEOUTS cto = { 0, 0, 0, 0, 0};
@@ -1991,6 +2128,7 @@ static int win_chr_init(WinCharState *s, const char *filename)
         fprintf(stderr, "Failed ClearCommError\n");
         goto fail;
     }
+    s->chr = chr;
     qemu_add_polling_cb(win_chr_poll, s);
     return 0;
 
@@ -2035,10 +2173,10 @@ static int win_chr_write(CharDriverState *chr, const uint8_t *buf, int len1)
 
 static int win_chr_read_poll(WinCharState *s)
 {
-    s->max_size = s->fd_can_read(s->win_opaque);
+    s->max_size = qemu_chr_can_read(s->chr);
     return s->max_size;
 }
-            
+
 static void win_chr_readfile(WinCharState *s)
 {
     int ret, err;
@@ -2056,7 +2194,7 @@ static void win_chr_readfile(WinCharState *s)
     }
 
     if (size > 0) {
-        s->fd_read(s->win_opaque, buf, size);
+        qemu_chr_read(s->chr, buf, size);
     }
 }
 
@@ -2086,18 +2224,7 @@ static int win_chr_poll(void *opaque)
     return 0;
 }
 
-static void win_chr_add_read_handler(CharDriverState *chr, 
-                                    IOCanRWHandler *fd_can_read, 
-                                    IOReadHandler *fd_read, void *opaque)
-{
-    WinCharState *s = chr->opaque;
-
-    s->fd_can_read = fd_can_read;
-    s->fd_read = fd_read;
-    s->win_opaque = opaque;
-}
-
-CharDriverState *qemu_chr_open_win(const char *filename)
+static CharDriverState *qemu_chr_open_win(const char *filename)
 {
     CharDriverState *chr;
     WinCharState *s;
@@ -2112,14 +2239,14 @@ CharDriverState *qemu_chr_open_win(const char *filename)
     }
     chr->opaque = s;
     chr->chr_write = win_chr_write;
-    chr->chr_add_read_handler = win_chr_add_read_handler;
     chr->chr_close = win_chr_close;
 
-    if (win_chr_init(s, filename) < 0) {
+    if (win_chr_init(s, chr, filename) < 0) {
         free(s);
         free(chr);
         return NULL;
     }
+    qemu_chr_reset(chr);
     return chr;
 }
 
@@ -2200,7 +2327,7 @@ static int win_chr_pipe_init(WinCharState *s, const char *filename)
 }
 
 
-CharDriverState *qemu_chr_open_win_pipe(const char *filename)
+static CharDriverState *qemu_chr_open_win_pipe(const char *filename)
 {
     CharDriverState *chr;
     WinCharState *s;
@@ -2215,7 +2342,6 @@ CharDriverState *qemu_chr_open_win_pipe(const char *filename)
     }
     chr->opaque = s;
     chr->chr_write = win_chr_write;
-    chr->chr_add_read_handler = win_chr_add_read_handler;
     chr->chr_close = win_chr_close;
     
     if (win_chr_pipe_init(s, filename) < 0) {
@@ -2223,10 +2349,11 @@ CharDriverState *qemu_chr_open_win_pipe(const char *filename)
         free(chr);
         return NULL;
     }
+    qemu_chr_reset(chr);
     return chr;
 }
 
-CharDriverState *qemu_chr_open_win_file(HANDLE fd_out)
+static CharDriverState *qemu_chr_open_win_file(HANDLE fd_out)
 {
     CharDriverState *chr;
     WinCharState *s;
@@ -2242,11 +2369,11 @@ CharDriverState *qemu_chr_open_win_file(HANDLE fd_out)
     s->hcom = fd_out;
     chr->opaque = s;
     chr->chr_write = win_chr_write;
-    chr->chr_add_read_handler = win_chr_add_read_handler;
+    qemu_chr_reset(chr);
     return chr;
 }
     
-CharDriverState *qemu_chr_open_win_file_out(const char *file_out)
+static CharDriverState *qemu_chr_open_win_file_out(const char *file_out)
 {
     HANDLE fd_out;
     
@@ -2263,9 +2390,6 @@ CharDriverState *qemu_chr_open_win_file_out(const char *file_out)
 /* UDP Net console */
 
 typedef struct {
-    IOCanRWHandler *fd_can_read;
-    IOReadHandler *fd_read;
-    void *fd_opaque;
     int fd;
     struct sockaddr_in daddr;
     char buf[1024];
@@ -2287,15 +2411,15 @@ static int udp_chr_read_poll(void *opaque)
     CharDriverState *chr = opaque;
     NetCharDriver *s = chr->opaque;
 
-    s->max_size = s->fd_can_read(s->fd_opaque);
+    s->max_size = qemu_chr_can_read(chr);
 
     /* If there were any stray characters in the queue process them
      * first
      */
     while (s->max_size > 0 && s->bufptr < s->bufcnt) {
-        s->fd_read(s->fd_opaque, &s->buf[s->bufptr], 1);
+        qemu_chr_read(chr, &s->buf[s->bufptr], 1);
         s->bufptr++;
-        s->max_size = s->fd_can_read(s->fd_opaque);
+        s->max_size = qemu_chr_can_read(chr);
     }
     return s->max_size;
 }
@@ -2314,33 +2438,31 @@ static void udp_chr_read(void *opaque)
 
     s->bufptr = 0;
     while (s->max_size > 0 && s->bufptr < s->bufcnt) {
-        s->fd_read(s->fd_opaque, &s->buf[s->bufptr], 1);
+        qemu_chr_read(chr, &s->buf[s->bufptr], 1);
         s->bufptr++;
-        s->max_size = s->fd_can_read(s->fd_opaque);
+        s->max_size = qemu_chr_can_read(chr);
     }
 }
 
-static void udp_chr_add_read_handler(CharDriverState *chr,
-                                    IOCanRWHandler *fd_can_read,
-                                    IOReadHandler *fd_read, void *opaque)
+static void udp_chr_update_read_handler(CharDriverState *chr)
 {
     NetCharDriver *s = chr->opaque;
 
     if (s->fd >= 0) {
-        s->fd_can_read = fd_can_read;
-        s->fd_read = fd_read;
-        s->fd_opaque = opaque;
         qemu_set_fd_handler2(s->fd, udp_chr_read_poll,
                              udp_chr_read, NULL, chr);
     }
 }
 
 int parse_host_port(struct sockaddr_in *saddr, const char *str);
+#ifndef _WIN32
+static int parse_unix_path(struct sockaddr_un *uaddr, const char *str);
+#endif
 int parse_host_src_port(struct sockaddr_in *haddr,
                         struct sockaddr_in *saddr,
                         const char *str);
 
-CharDriverState *qemu_chr_open_udp(const char *def)
+static CharDriverState *qemu_chr_open_udp(const char *def)
 {
     CharDriverState *chr = NULL;
     NetCharDriver *s = NULL;
@@ -2376,7 +2498,7 @@ CharDriverState *qemu_chr_open_udp(const char *def)
     s->bufptr = 0;
     chr->opaque = s;
     chr->chr_write = udp_chr_write;
-    chr->chr_add_read_handler = udp_chr_add_read_handler;
+    chr->chr_update_read_handler = udp_chr_update_read_handler;
     return chr;
 
 return_err:
@@ -2393,13 +2515,12 @@ return_err:
 /* TCP Net console */
 
 typedef struct {
-    IOCanRWHandler *fd_can_read;
-    IOReadHandler *fd_read;
-    void *fd_opaque;
     int fd, listen_fd;
     int connected;
     int max_size;
     int do_telnetopt;
+    int do_nodelay;
+    int is_unix;
 } TCPCharDriver;
 
 static void tcp_chr_accept(void *opaque);
@@ -2421,7 +2542,7 @@ static int tcp_chr_read_poll(void *opaque)
     TCPCharDriver *s = chr->opaque;
     if (!s->connected)
         return 0;
-    s->max_size = s->fd_can_read(s->fd_opaque);
+    s->max_size = qemu_chr_can_read(chr);
     return s->max_size;
 }
 
@@ -2454,7 +2575,7 @@ static void tcp_chr_process_IAC_bytes(CharDriverState *chr,
             } else {
                 if ((unsigned char)buf[i] == IAC_BREAK && s->do_telnetopt == 2) {
                     /* Handle IAC break commands by sending a serial break */
-                    chr->chr_event(s->fd_opaque, CHR_EVENT_BREAK);
+                    qemu_chr_event(chr, CHR_EVENT_BREAK);
                     s->do_telnetopt++;
                 }
                 s->do_telnetopt++;
@@ -2501,21 +2622,10 @@ static void tcp_chr_read(void *opaque)
         if (s->do_telnetopt)
             tcp_chr_process_IAC_bytes(chr, s, buf, &size);
         if (size > 0)
-            s->fd_read(s->fd_opaque, buf, size);
+            qemu_chr_read(chr, buf, size);
     }
 }
 
-static void tcp_chr_add_read_handler(CharDriverState *chr,
-                                     IOCanRWHandler *fd_can_read,
-                                    IOReadHandler *fd_read, void *opaque)
-{
-    TCPCharDriver *s = chr->opaque;
-
-    s->fd_can_read = fd_can_read;
-    s->fd_read = fd_read;
-    s->fd_opaque = opaque;
-}
-
 static void tcp_chr_connect(void *opaque)
 {
     CharDriverState *chr = opaque;
@@ -2524,6 +2634,7 @@ static void tcp_chr_connect(void *opaque)
     s->connected = 1;
     qemu_set_fd_handler2(s->fd, tcp_chr_read_poll,
                          tcp_chr_read, NULL, chr);
+    qemu_chr_reset(chr);
 }
 
 #define IACSET(x,a,b,c) x[0] = a; x[1] = b; x[2] = c;
@@ -2541,17 +2652,36 @@ static void tcp_chr_telnet_init(int fd)
     send(fd, (char *)buf, 3, 0);
 }
 
+static void socket_set_nodelay(int fd)
+{
+    int val = 1;
+    setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
+}
+
 static void tcp_chr_accept(void *opaque)
 {
     CharDriverState *chr = opaque;
     TCPCharDriver *s = chr->opaque;
     struct sockaddr_in saddr;
+#ifndef _WIN32
+    struct sockaddr_un uaddr;
+#endif
+    struct sockaddr *addr;
     socklen_t len;
     int fd;
 
     for(;;) {
-        len = sizeof(saddr);
-        fd = accept(s->listen_fd, (struct sockaddr *)&saddr, &len);
+#ifndef _WIN32
+       if (s->is_unix) {
+           len = sizeof(uaddr);
+           addr = (struct sockaddr *)&uaddr;
+       } else
+#endif
+       {
+           len = sizeof(saddr);
+           addr = (struct sockaddr *)&saddr;
+       }
+        fd = accept(s->listen_fd, addr, &len);
         if (fd < 0 && errno != EINTR) {
             return;
         } else if (fd >= 0) {
@@ -2561,6 +2691,8 @@ static void tcp_chr_accept(void *opaque)
         }
     }
     socket_set_nonblock(fd);
+    if (s->do_nodelay)
+        socket_set_nodelay(fd);
     s->fd = fd;
     qemu_set_fd_handler(s->listen_fd, NULL, NULL, NULL);
     tcp_chr_connect(chr);
@@ -2577,19 +2709,37 @@ static void tcp_chr_close(CharDriverState *chr)
 }
 
 static CharDriverState *qemu_chr_open_tcp(const char *host_str, 
-                                          int is_telnet)
+                                          int is_telnet,
+                                         int is_unix)
 {
     CharDriverState *chr = NULL;
     TCPCharDriver *s = NULL;
     int fd = -1, ret, err, val;
     int is_listen = 0;
     int is_waitconnect = 1;
+    int do_nodelay = 0;
     const char *ptr;
     struct sockaddr_in saddr;
-    int opt;
+#ifndef _WIN32
+    struct sockaddr_un uaddr;
+#endif
+    struct sockaddr *addr;
+    socklen_t addrlen;
 
-    if (parse_host_port(&saddr, host_str) < 0)
-        goto fail;
+#ifndef _WIN32
+    if (is_unix) {
+       addr = (struct sockaddr *)&uaddr;
+       addrlen = sizeof(uaddr);
+       if (parse_unix_path(&uaddr, host_str) < 0)
+           goto fail;
+    } else
+#endif
+    {
+       addr = (struct sockaddr *)&saddr;
+       addrlen = sizeof(saddr);
+       if (parse_host_port(&saddr, host_str) < 0)
+           goto fail;
+    }
 
     ptr = host_str;
     while((ptr = strchr(ptr,','))) {
@@ -2598,6 +2748,8 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str,
             is_listen = 1;
         } else if (!strncmp(ptr,"nowait",6)) {
             is_waitconnect = 0;
+        } else if (!strncmp(ptr,"nodelay",6)) {
+            do_nodelay = 1;
         } else {
             printf("Unknown option: %s\n", ptr);
             goto fail;
@@ -2612,8 +2764,14 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str,
     s = qemu_mallocz(sizeof(TCPCharDriver));
     if (!s)
         goto fail;
-    
-    fd = socket(PF_INET, SOCK_STREAM, 0);
+
+#ifndef _WIN32
+    if (is_unix)
+       fd = socket(PF_UNIX, SOCK_STREAM, 0);
+    else
+#endif
+       fd = socket(PF_INET, SOCK_STREAM, 0);
+       
     if (fd < 0) 
         goto fail;
 
@@ -2623,24 +2781,43 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str,
     s->connected = 0;
     s->fd = -1;
     s->listen_fd = -1;
+    s->is_unix = is_unix;
+    s->do_nodelay = do_nodelay && !is_unix;
+
+    chr->opaque = s;
+    chr->chr_write = tcp_chr_write;
+    chr->chr_close = tcp_chr_close;
+
     if (is_listen) {
         /* allow fast reuse */
-        val = 1;
-        setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val));
+#ifndef _WIN32
+       if (is_unix) {
+           char path[109];
+           strncpy(path, uaddr.sun_path, 108);
+           path[108] = 0;
+           unlink(path);
+       } else
+#endif
+       {
+           val = 1;
+           setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val));
+       }
         
-        ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr));
-        if (ret < 0) 
+        ret = bind(fd, addr, addrlen);
+        if (ret < 0)
             goto fail;
+
         ret = listen(fd, 0);
         if (ret < 0)
             goto fail;
+
         s->listen_fd = fd;
         qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr);
         if (is_telnet)
             s->do_telnetopt = 1;
     } else {
         for(;;) {
-            ret = connect(fd, (struct sockaddr *)&saddr, sizeof(saddr));
+            ret = connect(fd, addr, addrlen);
             if (ret < 0) {
                 err = socket_error();
                 if (err == EINTR || err == EWOULDBLOCK) {
@@ -2655,18 +2832,13 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str,
             }
         }
         s->fd = fd;
-       opt = 1;
-       setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&opt, sizeof(opt));
+        socket_set_nodelay(fd);
         if (s->connected)
             tcp_chr_connect(chr);
         else
             qemu_set_fd_handler(s->fd, NULL, tcp_chr_connect, chr);
     }
     
-    chr->opaque = s;
-    chr->chr_write = tcp_chr_write;
-    chr->chr_add_read_handler = tcp_chr_add_read_handler;
-    chr->chr_close = tcp_chr_close;
     if (is_listen && is_waitconnect) {
         printf("QEMU waiting for connection on: %s\n", host_str);
         tcp_chr_accept(chr);
@@ -2692,16 +2864,18 @@ CharDriverState *qemu_chr_open(const char *filename)
         return qemu_chr_open_null();
     } else 
     if (strstart(filename, "tcp:", &p)) {
-        return qemu_chr_open_tcp(p, 0);
+        return qemu_chr_open_tcp(p, 0, 0);
     } else
     if (strstart(filename, "telnet:", &p)) {
-        return qemu_chr_open_tcp(p, 1);
+        return qemu_chr_open_tcp(p, 1, 0);
     } else
     if (strstart(filename, "udp:", &p)) {
         return qemu_chr_open_udp(p);
     } else
 #ifndef _WIN32
-    if (strstart(filename, "file:", &p)) {
+    if (strstart(filename, "unix:", &p)) {
+       return qemu_chr_open_tcp(p, 0, 1);
+    } else if (strstart(filename, "file:", &p)) {
         return qemu_chr_open_file_out(p);
     } else if (strstart(filename, "pipe:", &p)) {
         return qemu_chr_open_pipe(p);
@@ -2882,6 +3056,26 @@ int parse_host_port(struct sockaddr_in *saddr, const char *str)
     return 0;
 }
 
+#ifndef _WIN32
+static int parse_unix_path(struct sockaddr_un *uaddr, const char *str)
+{
+    const char *p;
+    int len;
+
+    len = MIN(108, strlen(str));
+    p = strchr(str, ',');
+    if (p)
+       len = MIN(len, p - str);
+
+    memset(uaddr, 0, sizeof(*uaddr));
+
+    uaddr->sun_family = AF_UNIX;
+    memcpy(uaddr->sun_path, str, len);
+
+    return 0;
+}
+#endif
+
 /* find or alloc a new VLAN */
 VLANState *qemu_find_vlan(int id)
 {
@@ -3126,8 +3320,8 @@ void net_slirp_smb(const char *exported_dir)
     fclose(f);
     atexit(smb_exit);
 
-    snprintf(smb_cmdline, sizeof(smb_cmdline), "/usr/sbin/smbd -s %s",
-             smb_conf);
+    snprintf(smb_cmdline, sizeof(smb_cmdline), "%s -s %s",
+             SMBD_COMMAND, smb_conf);
     
     slirp_add_exec(0, smb_cmdline, 4, 139);
 }
@@ -3256,7 +3450,7 @@ static int net_tap_init(VLANState *vlan, const char *ifname1,
     if (fd < 0)
         return -1;
 
-    if (!setup_script)
+    if (!setup_script || !strcmp(setup_script, "no"))
         setup_script = "";
     if (setup_script[0] != '\0') {
         /* try to launch network init script */
@@ -3746,7 +3940,7 @@ static int get_param_value(char *buf, int buf_size,
     return 0;
 }
 
-int net_client_init(const char *str)
+static int net_client_init(const char *str)
 {
     const char *p;
     char *q;
@@ -3838,8 +4032,9 @@ int net_client_init(const char *str)
             if (net_tap_fd_init(vlan, fd))
                 ret = 0;
         } else {
-            ifname[0] = '\0';
-            get_param_value(ifname, sizeof(ifname), "ifname", p);
+            if (get_param_value(ifname, sizeof(ifname), "ifname", p) <= 0) {
+                ifname[0] = '\0';
+            }
             if (get_param_value(setup_script, sizeof(setup_script), "script", p) == 0) {
                 pstrcpy(setup_script, sizeof(setup_script), DEFAULT_NETWORK_SCRIPT);
             }
@@ -3890,7 +4085,7 @@ void do_info_network(void)
             term_printf("  %s\n", vc->info_str);
     }
 }
+
 /***********************************************************/
 /* USB devices */
 
@@ -4268,87 +4463,236 @@ void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
 /***********************************************************/
 /* savevm/loadvm support */
 
-void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size)
-{
-    fwrite(buf, 1, size, f);
-}
+#define IO_BUF_SIZE 32768
 
-void qemu_put_byte(QEMUFile *f, int v)
+struct QEMUFile {
+    FILE *outfile;
+    BlockDriverState *bs;
+    int is_file;
+    int is_writable;
+    int64_t base_offset;
+    int64_t buf_offset; /* start of buffer when writing, end of buffer
+                           when reading */
+    int buf_index;
+    int buf_size; /* 0 when writing */
+    uint8_t buf[IO_BUF_SIZE];
+};
+
+QEMUFile *qemu_fopen(const char *filename, const char *mode)
 {
-    fputc(v, f);
+    QEMUFile *f;
+
+    f = qemu_mallocz(sizeof(QEMUFile));
+    if (!f)
+        return NULL;
+    if (!strcmp(mode, "wb")) {
+        f->is_writable = 1;
+    } else if (!strcmp(mode, "rb")) {
+        f->is_writable = 0;
+    } else {
+        goto fail;
+    }
+    f->outfile = fopen(filename, mode);
+    if (!f->outfile)
+        goto fail;
+    f->is_file = 1;
+    return f;
+ fail:
+    if (f->outfile)
+        fclose(f->outfile);
+    qemu_free(f);
+    return NULL;
 }
 
-void qemu_put_be16(QEMUFile *f, unsigned int v)
+QEMUFile *qemu_fopen_bdrv(BlockDriverState *bs, int64_t offset, int is_writable)
 {
-    qemu_put_byte(f, v >> 8);
-    qemu_put_byte(f, v);
+    QEMUFile *f;
+
+    f = qemu_mallocz(sizeof(QEMUFile));
+    if (!f)
+        return NULL;
+    f->is_file = 0;
+    f->bs = bs;
+    f->is_writable = is_writable;
+    f->base_offset = offset;
+    return f;
 }
 
-void qemu_put_be32(QEMUFile *f, unsigned int v)
+void qemu_fflush(QEMUFile *f)
 {
-    qemu_put_byte(f, v >> 24);
-    qemu_put_byte(f, v >> 16);
-    qemu_put_byte(f, v >> 8);
-    qemu_put_byte(f, v);
+    if (!f->is_writable)
+        return;
+    if (f->buf_index > 0) {
+        if (f->is_file) {
+            fseek(f->outfile, f->buf_offset, SEEK_SET);
+            fwrite(f->buf, 1, f->buf_index, f->outfile);
+        } else {
+            bdrv_pwrite(f->bs, f->base_offset + f->buf_offset, 
+                        f->buf, f->buf_index);
+        }
+        f->buf_offset += f->buf_index;
+        f->buf_index = 0;
+    }
 }
 
-void qemu_put_be64(QEMUFile *f, uint64_t v)
+static void qemu_fill_buffer(QEMUFile *f)
 {
-    qemu_put_be32(f, v >> 32);
-    qemu_put_be32(f, v);
+    int len;
+
+    if (f->is_writable)
+        return;
+    if (f->is_file) {
+        fseek(f->outfile, f->buf_offset, SEEK_SET);
+        len = fread(f->buf, 1, IO_BUF_SIZE, f->outfile);
+        if (len < 0)
+            len = 0;
+    } else {
+        len = bdrv_pread(f->bs, f->base_offset + f->buf_offset, 
+                         f->buf, IO_BUF_SIZE);
+        if (len < 0)
+            len = 0;
+    }
+    f->buf_index = 0;
+    f->buf_size = len;
+    f->buf_offset += len;
 }
 
-int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size)
+void qemu_fclose(QEMUFile *f)
 {
-    return fread(buf, 1, size, f);
+    if (f->is_writable)
+        qemu_fflush(f);
+    if (f->is_file) {
+        fclose(f->outfile);
+    }
+    qemu_free(f);
 }
 
-int qemu_get_byte(QEMUFile *f)
+void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size)
 {
-    int v;
-    v = fgetc(f);
-    if (v == EOF)
-        return 0;
-    else
-        return v;
+    int l;
+    while (size > 0) {
+        l = IO_BUF_SIZE - f->buf_index;
+        if (l > size)
+            l = size;
+        memcpy(f->buf + f->buf_index, buf, l);
+        f->buf_index += l;
+        buf += l;
+        size -= l;
+        if (f->buf_index >= IO_BUF_SIZE)
+            qemu_fflush(f);
+    }
 }
 
-unsigned int qemu_get_be16(QEMUFile *f)
+void qemu_put_byte(QEMUFile *f, int v)
 {
-    unsigned int v;
-    v = qemu_get_byte(f) << 8;
-    v |= qemu_get_byte(f);
-    return v;
+    f->buf[f->buf_index++] = v;
+    if (f->buf_index >= IO_BUF_SIZE)
+        qemu_fflush(f);
 }
 
-unsigned int qemu_get_be32(QEMUFile *f)
+int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size1)
 {
-    unsigned int v;
-    v = qemu_get_byte(f) << 24;
-    v |= qemu_get_byte(f) << 16;
-    v |= qemu_get_byte(f) << 8;
-    v |= qemu_get_byte(f);
-    return v;
+    int size, l;
+
+    size = size1;
+    while (size > 0) {
+        l = f->buf_size - f->buf_index;
+        if (l == 0) {
+            qemu_fill_buffer(f);
+            l = f->buf_size - f->buf_index;
+            if (l == 0)
+                break;
+        }
+        if (l > size)
+            l = size;
+        memcpy(buf, f->buf + f->buf_index, l);
+        f->buf_index += l;
+        buf += l;
+        size -= l;
+    }
+    return size1 - size;
 }
 
-uint64_t qemu_get_be64(QEMUFile *f)
+int qemu_get_byte(QEMUFile *f)
 {
-    uint64_t v;
-    v = (uint64_t)qemu_get_be32(f) << 32;
-    v |= qemu_get_be32(f);
-    return v;
+    if (f->buf_index >= f->buf_size) {
+        qemu_fill_buffer(f);
+        if (f->buf_index >= f->buf_size)
+            return 0;
+    }
+    return f->buf[f->buf_index++];
 }
 
 int64_t qemu_ftell(QEMUFile *f)
 {
-    return ftell(f);
+    return f->buf_offset - f->buf_size + f->buf_index;
 }
 
 int64_t qemu_fseek(QEMUFile *f, int64_t pos, int whence)
 {
-    if (fseek(f, pos, whence) < 0)
+    if (whence == SEEK_SET) {
+        /* nothing to do */
+    } else if (whence == SEEK_CUR) {
+        pos += qemu_ftell(f);
+    } else {
+        /* SEEK_END not supported */
         return -1;
-    return ftell(f);
+    }
+    if (f->is_writable) {
+        qemu_fflush(f);
+        f->buf_offset = pos;
+    } else {
+        f->buf_offset = pos;
+        f->buf_index = 0;
+        f->buf_size = 0;
+    }
+    return pos;
+}
+
+void qemu_put_be16(QEMUFile *f, unsigned int v)
+{
+    qemu_put_byte(f, v >> 8);
+    qemu_put_byte(f, v);
+}
+
+void qemu_put_be32(QEMUFile *f, unsigned int v)
+{
+    qemu_put_byte(f, v >> 24);
+    qemu_put_byte(f, v >> 16);
+    qemu_put_byte(f, v >> 8);
+    qemu_put_byte(f, v);
+}
+
+void qemu_put_be64(QEMUFile *f, uint64_t v)
+{
+    qemu_put_be32(f, v >> 32);
+    qemu_put_be32(f, v);
+}
+
+unsigned int qemu_get_be16(QEMUFile *f)
+{
+    unsigned int v;
+    v = qemu_get_byte(f) << 8;
+    v |= qemu_get_byte(f);
+    return v;
+}
+
+unsigned int qemu_get_be32(QEMUFile *f)
+{
+    unsigned int v;
+    v = qemu_get_byte(f) << 24;
+    v |= qemu_get_byte(f) << 16;
+    v |= qemu_get_byte(f) << 8;
+    v |= qemu_get_byte(f);
+    return v;
+}
+
+uint64_t qemu_get_be64(QEMUFile *f)
+{
+    uint64_t v;
+    v = (uint64_t)qemu_get_be32(f) << 32;
+    v |= qemu_get_be32(f);
+    return v;
 }
 
 typedef struct SaveStateEntry {
@@ -4392,25 +4736,18 @@ int register_savevm(const char *idstr,
 }
 
 #define QEMU_VM_FILE_MAGIC   0x5145564d
-#define QEMU_VM_FILE_VERSION 0x00000001
+#define QEMU_VM_FILE_VERSION 0x00000002
 
-int qemu_savevm(const char *filename)
+int qemu_savevm_state(QEMUFile *f)
 {
     SaveStateEntry *se;
-    QEMUFile *f;
-    int len, len_pos, cur_pos, saved_vm_running, ret;
-
-    saved_vm_running = vm_running;
-    vm_stop(0);
-
-    f = fopen(filename, "wb");
-    if (!f) {
-        ret = -1;
-        goto the_end;
-    }
+    int len, ret;
+    int64_t cur_pos, len_pos, total_len_pos;
 
     qemu_put_be32(f, QEMU_VM_FILE_MAGIC);
     qemu_put_be32(f, QEMU_VM_FILE_VERSION);
+    total_len_pos = qemu_ftell(f);
+    qemu_put_be64(f, 0); /* total size */
 
     for(se = first_se; se != NULL; se = se->next) {
         /* ID string */
@@ -4422,24 +4759,24 @@ int qemu_savevm(const char *filename)
         qemu_put_be32(f, se->version_id);
 
         /* record size: filled later */
-        len_pos = ftell(f);
+        len_pos = qemu_ftell(f);
         qemu_put_be32(f, 0);
         
         se->save_state(f, se->opaque);
 
         /* fill record size */
-        cur_pos = ftell(f);
-        len = ftell(f) - len_pos - 4;
-        fseek(f, len_pos, SEEK_SET);
+        cur_pos = qemu_ftell(f);
+        len = cur_pos - len_pos - 4;
+        qemu_fseek(f, len_pos, SEEK_SET);
         qemu_put_be32(f, len);
-        fseek(f, cur_pos, SEEK_SET);
+        qemu_fseek(f, cur_pos, SEEK_SET);
     }
+    cur_pos = qemu_ftell(f);
+    qemu_fseek(f, total_len_pos, SEEK_SET);
+    qemu_put_be64(f, cur_pos - total_len_pos - 8);
+    qemu_fseek(f, cur_pos, SEEK_SET);
 
-    fclose(f);
     ret = 0;
- the_end:
-    if (saved_vm_running)
-        vm_start();
     return ret;
 }
 
@@ -4455,38 +4792,29 @@ static SaveStateEntry *find_se(const char *idstr, int instance_id)
     return NULL;
 }
 
-int qemu_loadvm(const char *filename)
+int qemu_loadvm_state(QEMUFile *f)
 {
     SaveStateEntry *se;
-    QEMUFile *f;
-    int len, cur_pos, ret, instance_id, record_len, version_id;
-    int saved_vm_running;
+    int len, ret, instance_id, record_len, version_id;
+    int64_t total_len, end_pos, cur_pos;
     unsigned int v;
     char idstr[256];
     
-    saved_vm_running = vm_running;
-    vm_stop(0);
-
-    f = fopen(filename, "rb");
-    if (!f) {
-        ret = -1;
-        goto the_end;
-    }
-
     v = qemu_get_be32(f);
     if (v != QEMU_VM_FILE_MAGIC)
         goto fail;
     v = qemu_get_be32(f);
     if (v != QEMU_VM_FILE_VERSION) {
     fail:
-        fclose(f);
         ret = -1;
         goto the_end;
     }
+    total_len = qemu_get_be64(f);
+    end_pos = total_len + qemu_ftell(f);
     for(;;) {
-        len = qemu_get_byte(f);
-        if (feof(f))
+        if (qemu_ftell(f) >= end_pos)
             break;
+        len = qemu_get_byte(f);
         qemu_get_buffer(f, idstr, len);
         idstr[len] = '\0';
         instance_id = qemu_get_be32(f);
@@ -4496,7 +4824,7 @@ int qemu_loadvm(const char *filename)
         printf("idstr=%s instance=0x%x version=%d len=%d\n", 
                idstr, instance_id, version_id, record_len);
 #endif
-        cur_pos = ftell(f);
+        cur_pos = qemu_ftell(f);
         se = find_se(idstr, instance_id);
         if (!se) {
             fprintf(stderr, "qemu: warning: instance 0x%x of device '%s' not present in current VM\n", 
@@ -4511,17 +4839,302 @@ int qemu_loadvm(const char *filename)
         /* always seek to exact end of record */
         qemu_fseek(f, cur_pos + record_len, SEEK_SET);
     }
-    fclose(f);
+    ret = 0;
+ the_end:
+    return ret;
+}
+
+/* device can contain snapshots */
+static int bdrv_can_snapshot(BlockDriverState *bs)
+{
+    return (bs &&
+            !bdrv_is_removable(bs) &&
+            !bdrv_is_read_only(bs));
+}
+
+/* device must be snapshots in order to have a reliable snapshot */
+static int bdrv_has_snapshot(BlockDriverState *bs)
+{
+    return (bs &&
+            !bdrv_is_removable(bs) &&
+            !bdrv_is_read_only(bs));
+}
+
+static BlockDriverState *get_bs_snapshots(void)
+{
+    BlockDriverState *bs;
+    int i;
+
+    if (bs_snapshots)
+        return bs_snapshots;
+    for(i = 0; i <= MAX_DISKS; i++) {
+        bs = bs_table[i];
+        if (bdrv_can_snapshot(bs))
+            goto ok;
+    }
+    return NULL;
+ ok:
+    bs_snapshots = bs;
+    return bs;
+}
+
+static int bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info,
+                              const char *name)
+{
+    QEMUSnapshotInfo *sn_tab, *sn;
+    int nb_sns, i, ret;
+    
+    ret = -ENOENT;
+    nb_sns = bdrv_snapshot_list(bs, &sn_tab);
+    if (nb_sns < 0)
+        return ret;
+    for(i = 0; i < nb_sns; i++) {
+        sn = &sn_tab[i];
+        if (!strcmp(sn->id_str, name) || !strcmp(sn->name, name)) {
+            *sn_info = *sn;
+            ret = 0;
+            break;
+        }
+    }
+    qemu_free(sn_tab);
+    return ret;
+}
+
+void do_savevm(const char *name)
+{
+    BlockDriverState *bs, *bs1;
+    QEMUSnapshotInfo sn1, *sn = &sn1, old_sn1, *old_sn = &old_sn1;
+    int must_delete, ret, i;
+    BlockDriverInfo bdi1, *bdi = &bdi1;
+    QEMUFile *f;
+    int saved_vm_running;
+#ifdef _WIN32
+    struct _timeb tb;
+#else
+    struct timeval tv;
+#endif
+
+    bs = get_bs_snapshots();
+    if (!bs) {
+        term_printf("No block device can accept snapshots\n");
+        return;
+    }
+
+    /* ??? Should this occur after vm_stop?  */
+    qemu_aio_flush();
+
+    saved_vm_running = vm_running;
+    vm_stop(0);
+    
+    must_delete = 0;
+    if (name) {
+        ret = bdrv_snapshot_find(bs, old_sn, name);
+        if (ret >= 0) {
+            must_delete = 1;
+        }
+    }
+    memset(sn, 0, sizeof(*sn));
+    if (must_delete) {
+        pstrcpy(sn->name, sizeof(sn->name), old_sn->name);
+        pstrcpy(sn->id_str, sizeof(sn->id_str), old_sn->id_str);
+    } else {
+        if (name)
+            pstrcpy(sn->name, sizeof(sn->name), name);
+    }
+
+    /* fill auxiliary fields */
+#ifdef _WIN32
+    _ftime(&tb);
+    sn->date_sec = tb.time;
+    sn->date_nsec = tb.millitm * 1000000;
+#else
+    gettimeofday(&tv, NULL);
+    sn->date_sec = tv.tv_sec;
+    sn->date_nsec = tv.tv_usec * 1000;
+#endif
+    sn->vm_clock_nsec = qemu_get_clock(vm_clock);
+    
+    if (bdrv_get_info(bs, bdi) < 0 || bdi->vm_state_offset <= 0) {
+        term_printf("Device %s does not support VM state snapshots\n",
+                    bdrv_get_device_name(bs));
+        goto the_end;
+    }
+    
+    /* save the VM state */
+    f = qemu_fopen_bdrv(bs, bdi->vm_state_offset, 1);
+    if (!f) {
+        term_printf("Could not open VM state file\n");
+        goto the_end;
+    }
+    ret = qemu_savevm_state(f);
+    sn->vm_state_size = qemu_ftell(f);
+    qemu_fclose(f);
+    if (ret < 0) {
+        term_printf("Error %d while writing VM\n", ret);
+        goto the_end;
+    }
+    
+    /* create the snapshots */
+
+    for(i = 0; i < MAX_DISKS; i++) {
+        bs1 = bs_table[i];
+        if (bdrv_has_snapshot(bs1)) {
+            if (must_delete) {
+                ret = bdrv_snapshot_delete(bs1, old_sn->id_str);
+                if (ret < 0) {
+                    term_printf("Error while deleting snapshot on '%s'\n",
+                                bdrv_get_device_name(bs1));
+                }
+            }
+            ret = bdrv_snapshot_create(bs1, sn);
+            if (ret < 0) {
+                term_printf("Error while creating snapshot on '%s'\n",
+                            bdrv_get_device_name(bs1));
+            }
+        }
+    }
+
+ the_end:
+    if (saved_vm_running)
+        vm_start();
+}
+
+void do_loadvm(const char *name)
+{
+    BlockDriverState *bs, *bs1;
+    BlockDriverInfo bdi1, *bdi = &bdi1;
+    QEMUFile *f;
+    int i, ret;
+    int saved_vm_running;
+
+    bs = get_bs_snapshots();
+    if (!bs) {
+        term_printf("No block device supports snapshots\n");
+        return;
+    }
+    
+    /* Flush all IO requests so they don't interfere with the new state.  */
+    qemu_aio_flush();
+
+    saved_vm_running = vm_running;
+    vm_stop(0);
+
+    for(i = 0; i <= MAX_DISKS; i++) {
+        bs1 = bs_table[i];
+        if (bdrv_has_snapshot(bs1)) {
+            ret = bdrv_snapshot_goto(bs1, name);
+            if (ret < 0) {
+                if (bs != bs1)
+                    term_printf("Warning: ");
+                switch(ret) {
+                case -ENOTSUP:
+                    term_printf("Snapshots not supported on device '%s'\n",
+                                bdrv_get_device_name(bs1));
+                    break;
+                case -ENOENT:
+                    term_printf("Could not find snapshot '%s' on device '%s'\n",
+                                name, bdrv_get_device_name(bs1));
+                    break;
+                default:
+                    term_printf("Error %d while activating snapshot on '%s'\n",
+                                ret, bdrv_get_device_name(bs1));
+                    break;
+                }
+                /* fatal on snapshot block device */
+                if (bs == bs1)
+                    goto the_end;
+            }
+        }
+    }
+
+    if (bdrv_get_info(bs, bdi) < 0 || bdi->vm_state_offset <= 0) {
+        term_printf("Device %s does not support VM state snapshots\n",
+                    bdrv_get_device_name(bs));
+        return;
+    }
+    
+    /* restore the VM state */
+    f = qemu_fopen_bdrv(bs, bdi->vm_state_offset, 0);
+    if (!f) {
+        term_printf("Could not open VM state file\n");
+        goto the_end;
+    }
+    ret = qemu_loadvm_state(f);
+    qemu_fclose(f);
+    if (ret < 0) {
+        term_printf("Error %d while loading VM state\n", ret);
+    }
 
     /* del tmp file */
-    if (unlink(filename) == -1)
+    if (unlink(name) == -1)
         fprintf(stderr, "delete tmp qemu state file failed.\n");
 
-    ret = 0;
  the_end:
     if (saved_vm_running)
         vm_start();
-    return ret;
+}
+
+void do_delvm(const char *name)
+{
+    BlockDriverState *bs, *bs1;
+    int i, ret;
+
+    bs = get_bs_snapshots();
+    if (!bs) {
+        term_printf("No block device supports snapshots\n");
+        return;
+    }
+    
+    for(i = 0; i <= MAX_DISKS; i++) {
+        bs1 = bs_table[i];
+        if (bdrv_has_snapshot(bs1)) {
+            ret = bdrv_snapshot_delete(bs1, name);
+            if (ret < 0) {
+                if (ret == -ENOTSUP)
+                    term_printf("Snapshots not supported on device '%s'\n",
+                                bdrv_get_device_name(bs1));
+                else
+                    term_printf("Error %d while deleting snapshot on '%s'\n",
+                                ret, bdrv_get_device_name(bs1));
+            }
+        }
+    }
+}
+
+void do_info_snapshots(void)
+{
+    BlockDriverState *bs, *bs1;
+    QEMUSnapshotInfo *sn_tab, *sn;
+    int nb_sns, i;
+    char buf[256];
+
+    bs = get_bs_snapshots();
+    if (!bs) {
+        term_printf("No available block device supports snapshots\n");
+        return;
+    }
+    term_printf("Snapshot devices:");
+    for(i = 0; i <= MAX_DISKS; i++) {
+        bs1 = bs_table[i];
+        if (bdrv_has_snapshot(bs1)) {
+            if (bs == bs1)
+                term_printf(" %s", bdrv_get_device_name(bs1));
+        }
+    }
+    term_printf("\n");
+
+    nb_sns = bdrv_snapshot_list(bs, &sn_tab);
+    if (nb_sns < 0) {
+        term_printf("bdrv_snapshot_list: error %d\n", nb_sns);
+        return;
+    }
+    term_printf("Snapshot list (from %s):\n", bdrv_get_device_name(bs));
+    term_printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
+    for(i = 0; i < nb_sns; i++) {
+        sn = &sn_tab[i];
+        term_printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn));
+    }
+    qemu_free(sn_tab);
 }
 
 #ifndef CONFIG_DM
@@ -4636,6 +5249,7 @@ void cpu_save(QEMUFile *f, void *opaque)
     qemu_put_be64s(f, &env->fmask);
     qemu_put_be64s(f, &env->kernelgsbase);
 #endif
+    qemu_put_be32s(f, &env->smbase);
 }
 
 #ifdef USE_X86LDOUBLE
@@ -4669,7 +5283,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
     uint32_t hflags;
     uint16_t fpus, fpuc, fptag, fpregs_format;
 
-    if (version_id != 3)
+    if (version_id != 3 && version_id != 4)
         return -EINVAL;
     for(i = 0; i < CPU_NB_REGS; i++)
         qemu_get_betls(f, &env->regs[i]);
@@ -4772,6 +5386,8 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
     qemu_get_be64s(f, &env->fmask);
     qemu_get_be64s(f, &env->kernelgsbase);
 #endif
+    if (version_id >= 4) 
+        qemu_get_be32s(f, &env->smbase);
 
     /* XXX: compute hflags from scratch, except for CPL and IIF */
     env->hflags = hflags;
@@ -4897,24 +5513,6 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
 /***********************************************************/
 /* ram save/restore */
 
-/* we just avoid storing empty pages */
-static void ram_put_page(QEMUFile *f, const uint8_t *buf, int len)
-{
-    int i, v;
-
-    v = buf[0];
-    for(i = 1; i < len; i++) {
-        if (buf[i] != v)
-            goto normal_save;
-    }
-    qemu_put_byte(f, 1);
-    qemu_put_byte(f, v);
-    return;
- normal_save:
-    qemu_put_byte(f, 0); 
-    qemu_put_buffer(f, buf, len);
-}
-
 static int ram_get_page(QEMUFile *f, uint8_t *buf, int len)
 {
     int v;
@@ -4935,28 +5533,238 @@ static int ram_get_page(QEMUFile *f, uint8_t *buf, int len)
     return 0;
 }
 
+static int ram_load_v1(QEMUFile *f, void *opaque)
+{
+    int i, ret;
+
+    if (qemu_get_be32(f) != phys_ram_size)
+        return -EINVAL;
+    for(i = 0; i < phys_ram_size; i+= TARGET_PAGE_SIZE) {
+        ret = ram_get_page(f, phys_ram_base + i, TARGET_PAGE_SIZE);
+        if (ret)
+            return ret;
+    }
+    return 0;
+}
+
+#define BDRV_HASH_BLOCK_SIZE 1024
+#define IOBUF_SIZE 4096
+#define RAM_CBLOCK_MAGIC 0xfabe
+
+typedef struct RamCompressState {
+    z_stream zstream;
+    QEMUFile *f;
+    uint8_t buf[IOBUF_SIZE];
+} RamCompressState;
+
+static int ram_compress_open(RamCompressState *s, QEMUFile *f)
+{
+    int ret;
+    memset(s, 0, sizeof(*s));
+    s->f = f;
+    ret = deflateInit2(&s->zstream, 1,
+                       Z_DEFLATED, 15, 
+                       9, Z_DEFAULT_STRATEGY);
+    if (ret != Z_OK)
+        return -1;
+    s->zstream.avail_out = IOBUF_SIZE;
+    s->zstream.next_out = s->buf;
+    return 0;
+}
+
+static void ram_put_cblock(RamCompressState *s, const uint8_t *buf, int len)
+{
+    qemu_put_be16(s->f, RAM_CBLOCK_MAGIC);
+    qemu_put_be16(s->f, len);
+    qemu_put_buffer(s->f, buf, len);
+}
+
+static int ram_compress_buf(RamCompressState *s, const uint8_t *buf, int len)
+{
+    int ret;
+
+    s->zstream.avail_in = len;
+    s->zstream.next_in = (uint8_t *)buf;
+    while (s->zstream.avail_in > 0) {
+        ret = deflate(&s->zstream, Z_NO_FLUSH);
+        if (ret != Z_OK)
+            return -1;
+        if (s->zstream.avail_out == 0) {
+            ram_put_cblock(s, s->buf, IOBUF_SIZE);
+            s->zstream.avail_out = IOBUF_SIZE;
+            s->zstream.next_out = s->buf;
+        }
+    }
+    return 0;
+}
+
+static void ram_compress_close(RamCompressState *s)
+{
+    int len, ret;
+
+    /* compress last bytes */
+    for(;;) {
+        ret = deflate(&s->zstream, Z_FINISH);
+        if (ret == Z_OK || ret == Z_STREAM_END) {
+            len = IOBUF_SIZE - s->zstream.avail_out;
+            if (len > 0) {
+                ram_put_cblock(s, s->buf, len);
+            }
+            s->zstream.avail_out = IOBUF_SIZE;
+            s->zstream.next_out = s->buf;
+            if (ret == Z_STREAM_END)
+                break;
+        } else {
+            goto fail;
+        }
+    }
+fail:
+    deflateEnd(&s->zstream);
+}
+
+typedef struct RamDecompressState {
+    z_stream zstream;
+    QEMUFile *f;
+    uint8_t buf[IOBUF_SIZE];
+} RamDecompressState;
+
+static int ram_decompress_open(RamDecompressState *s, QEMUFile *f)
+{
+    int ret;
+    memset(s, 0, sizeof(*s));
+    s->f = f;
+    ret = inflateInit(&s->zstream);
+    if (ret != Z_OK)
+        return -1;
+    return 0;
+}
+
+static int ram_decompress_buf(RamDecompressState *s, uint8_t *buf, int len)
+{
+    int ret, clen;
+
+    s->zstream.avail_out = len;
+    s->zstream.next_out = buf;
+    while (s->zstream.avail_out > 0) {
+        if (s->zstream.avail_in == 0) {
+            if (qemu_get_be16(s->f) != RAM_CBLOCK_MAGIC)
+                return -1;
+            clen = qemu_get_be16(s->f);
+            if (clen > IOBUF_SIZE)
+                return -1;
+            qemu_get_buffer(s->f, s->buf, clen);
+            s->zstream.avail_in = clen;
+            s->zstream.next_in = s->buf;
+        }
+        ret = inflate(&s->zstream, Z_PARTIAL_FLUSH);
+        if (ret != Z_OK && ret != Z_STREAM_END) {
+            return -1;
+        }
+    }
+    return 0;
+}
+
+static void ram_decompress_close(RamDecompressState *s)
+{
+    inflateEnd(&s->zstream);
+}
+
 static void ram_save(QEMUFile *f, void *opaque)
 {
     int i;
+    RamCompressState s1, *s = &s1;
+    uint8_t buf[10];
+    
     qemu_put_be32(f, phys_ram_size);
-    for(i = 0; i < phys_ram_size; i+= TARGET_PAGE_SIZE) {
-        ram_put_page(f, phys_ram_base + i, TARGET_PAGE_SIZE);
+    if (ram_compress_open(s, f) < 0)
+        return;
+    for(i = 0; i < phys_ram_size; i+= BDRV_HASH_BLOCK_SIZE) {
+#if 0
+        if (tight_savevm_enabled) {
+            int64_t sector_num;
+            int j;
+
+            /* find if the memory block is available on a virtual
+               block device */
+            sector_num = -1;
+            for(j = 0; j < MAX_DISKS; j++) {
+                if (bs_table[j]) {
+                    sector_num = bdrv_hash_find(bs_table[j], 
+                                                phys_ram_base + i, BDRV_HASH_BLOCK_SIZE);
+                    if (sector_num >= 0)
+                        break;
+                }
+            }
+            if (j == MAX_DISKS)
+                goto normal_compress;
+            buf[0] = 1;
+            buf[1] = j;
+            cpu_to_be64wu((uint64_t *)(buf + 2), sector_num);
+            ram_compress_buf(s, buf, 10);
+        } else 
+#endif
+        {
+            //        normal_compress:
+            buf[0] = 0;
+            ram_compress_buf(s, buf, 1);
+            ram_compress_buf(s, phys_ram_base + i, BDRV_HASH_BLOCK_SIZE);
+        }
     }
+    ram_compress_close(s);
 }
 
 static int ram_load(QEMUFile *f, void *opaque, int version_id)
 {
-    int i, ret;
+    RamDecompressState s1, *s = &s1;
+    uint8_t buf[10];
+    int i;
 
-    if (version_id != 1)
+    if (version_id == 1)
+        return ram_load_v1(f, opaque);
+    if (version_id != 2)
         return -EINVAL;
     if (qemu_get_be32(f) != phys_ram_size)
         return -EINVAL;
-    for(i = 0; i < phys_ram_size; i+= TARGET_PAGE_SIZE) {
-        ret = ram_get_page(f, phys_ram_base + i, TARGET_PAGE_SIZE);
-        if (ret)
-            return ret;
+    if (ram_decompress_open(s, f) < 0)
+        return -EINVAL;
+    for(i = 0; i < phys_ram_size; i+= BDRV_HASH_BLOCK_SIZE) {
+        if (ram_decompress_buf(s, buf, 1) < 0) {
+            fprintf(stderr, "Error while reading ram block header\n");
+            goto error;
+        }
+        if (buf[0] == 0) {
+            if (ram_decompress_buf(s, phys_ram_base + i, BDRV_HASH_BLOCK_SIZE) < 0) {
+                fprintf(stderr, "Error while reading ram block address=0x%08x", i);
+                goto error;
+            }
+        } else 
+#if 0
+        if (buf[0] == 1) {
+            int bs_index;
+            int64_t sector_num;
+
+            ram_decompress_buf(s, buf + 1, 9);
+            bs_index = buf[1];
+            sector_num = be64_to_cpupu((const uint64_t *)(buf + 2));
+            if (bs_index >= MAX_DISKS || bs_table[bs_index] == NULL) {
+                fprintf(stderr, "Invalid block device index %d\n", bs_index);
+                goto error;
+            }
+            if (bdrv_read(bs_table[bs_index], sector_num, phys_ram_base + i, 
+                          BDRV_HASH_BLOCK_SIZE / 512) < 0) {
+                fprintf(stderr, "Error while reading sector %d:%" PRId64 "\n", 
+                        bs_index, sector_num);
+                goto error;
+            }
+        } else 
+#endif
+        {
+        error:
+            printf("Error block header\n");
+            return -EINVAL;
+        }
     }
+    ram_decompress_close(s);
     return 0;
 }
 #else  /* CONFIG_DM */
@@ -4979,6 +5787,81 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
 }
 #endif /* CONFIG_DM */
 
+/***********************************************************/
+/* bottom halves (can be seen as timers which expire ASAP) */
+
+struct QEMUBH {
+    QEMUBHFunc *cb;
+    void *opaque;
+    int scheduled;
+    QEMUBH *next;
+};
+
+static QEMUBH *first_bh = NULL;
+
+QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque)
+{
+    QEMUBH *bh;
+    bh = qemu_mallocz(sizeof(QEMUBH));
+    if (!bh)
+        return NULL;
+    bh->cb = cb;
+    bh->opaque = opaque;
+    return bh;
+}
+
+int qemu_bh_poll(void)
+{
+    QEMUBH *bh, **pbh;
+    int ret;
+
+    ret = 0;
+    for(;;) {
+        pbh = &first_bh;
+        bh = *pbh;
+        if (!bh)
+            break;
+        ret = 1;
+        *pbh = bh->next;
+        bh->scheduled = 0;
+        bh->cb(bh->opaque);
+    }
+    return ret;
+}
+
+void qemu_bh_schedule(QEMUBH *bh)
+{
+    CPUState *env = cpu_single_env;
+    if (bh->scheduled)
+        return;
+    bh->scheduled = 1;
+    bh->next = first_bh;
+    first_bh = bh;
+
+    /* stop the currently executing CPU to execute the BH ASAP */
+    if (env) {
+        cpu_interrupt(env, CPU_INTERRUPT_EXIT);
+    }
+}
+
+void qemu_bh_cancel(QEMUBH *bh)
+{
+    QEMUBH **pbh;
+    if (bh->scheduled) {
+        pbh = &first_bh;
+        while (*pbh != bh)
+            pbh = &(*pbh)->next;
+        *pbh = bh->next;
+        bh->scheduled = 0;
+    }
+}
+
+void qemu_bh_delete(QEMUBH *bh)
+{
+    qemu_bh_cancel(bh);
+    qemu_free(bh);
+}
+
 /***********************************************************/
 /* machine registration */
 
@@ -5132,7 +6015,11 @@ void qemu_system_reset(void)
 
 void qemu_system_reset_request(void)
 {
-    reset_requested = 1;
+    if (no_reboot) {
+        shutdown_requested = 1;
+    } else {
+        reset_requested = 1;
+    }
     if (cpu_single_env)
         cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT);
 }
@@ -5236,9 +6123,8 @@ void main_loop_wait(int timeout)
         slirp_select_poll(&rfds, &wfds, &xfds);
     }
 #endif
-#ifdef _WIN32
-    tap_win32_poll();
-#endif
+    qemu_aio_poll();
+    qemu_bh_poll();
 
     if (vm_running) {
         qemu_run_timers(&active_timers[QEMU_TIMER_VIRTUAL], 
@@ -5331,7 +6217,7 @@ int main_loop(void)
 
 void help(void)
 {
-    printf("QEMU PC emulator version " QEMU_VERSION ", Copyright (c) 2003-2005 Fabrice Bellard\n"
+    printf("QEMU PC emulator version " QEMU_VERSION ", Copyright (c) 2003-2007 Fabrice Bellard\n"
            "usage: %s [options] [disk_image]\n"
            "\n"
            "'disk_image' is a raw hard image image for IDE hard disk 0\n"
@@ -5344,8 +6230,11 @@ void help(void)
            "-hdc/-hdd file  use 'file' as IDE hard disk 2/3 image\n"
            "-cdrom file     use 'file' as IDE cdrom image (cdrom is ide1 master)\n"
 #endif /* !CONFIG_DM */
-           "-boot [a|c|d]   boot on floppy (a), hard disk (c) or CD-ROM (d)\n"
-          "-snapshot       write to temporary files instead of disk image files\n"
+           "-boot [a|c|d|n] boot on floppy (a), hard disk (c), CD-ROM (d), or network (n)\n"
+           "-snapshot       write to temporary files instead of disk image files\n"
+#ifdef CONFIG_SDL
+           "-no-quit        disable SDL window close capability\n"
+#endif
 #ifdef TARGET_I386
            "-no-fd-bootchk  disable boot signature checking for floppy disks\n"
 #endif
@@ -5354,7 +6243,7 @@ void help(void)
            "-nographic      disable graphical output and redirect serial I/Os to console\n"
            "-vcpus          set CPU number of guest platform\n"
 #ifndef _WIN32
-          "-k language     use keyboard layout (for example \"fr\" for French)\n"
+           "-k language     use keyboard layout (for example \"fr\" for French)\n"
 #endif
 #ifdef HAS_AUDIO
            "-audio-help     print list of audio drivers and their options\n"
@@ -5389,6 +6278,7 @@ void help(void)
            "-net tap[,vlan=n][,fd=h][,ifname=name][,script=file][,bridge=br]\n"
            "                connect the host TAP network interface to VLAN 'n' and use\n"
            "                the network script 'file' (default=%s);\n"
+           "                use 'script=no' to disable script execution;\n"
            "                use 'fd=h' to connect to an already opened TAP interface\n"
 #endif
            "-net socket[,vlan=n][,fd=h][,listen=[host]:port][,connect=host:port]\n"
@@ -5425,7 +6315,7 @@ void help(void)
            "-domain-name    domain name that we're serving\n"
            "-hdachs c,h,s[,t]  force hard disk 0 physical geometry and the optional BIOS\n"
            "                translation (t=none or lba) (usually qemu can guess them)\n"
-           "-L path         set the directory for the BIOS and VGA BIOS\n"
+           "-L path         set the directory for the BIOS, VGA BIOS and keymaps\n"
 #ifdef USE_KQEMU
            "-kernel-kqemu   enable KQEMU full virtualization (default is user mode only)\n"
            "-no-kqemu       disable KQEMU kernel module usage\n"
@@ -5438,12 +6328,17 @@ void help(void)
            "                (default is CL-GD5446 PCI VGA)\n"
            "-no-acpi        disable ACPI\n"
 #endif
+           "-no-reboot      exit instead of rebooting\n"
            "-loadvm file    start right away with a saved state (loadvm in monitor)\n"
           "-vnc display    start a VNC server on display\n"
            "-vncviewer      start a vncviewer process for this domain\n"
            "-vncunused      bind the VNC server to an unused port\n"
            "-vnclisten      bind the VNC server to this address\n"
            "-timeoffset     time offset (in seconds) from local time\n"
+#ifndef _WIN32
+          "-daemonize      daemonize QEMU after initializing\n"
+#endif
+          "-option-rom rom load a file, rom, into the option ROM space\n"
            "-acpi           disable or enable ACPI of HVM domain \n"
            "\n"
            "During emulation, the following keys are useful:\n"
@@ -5519,6 +6414,7 @@ enum {
     QEMU_OPTION_parallel,
     QEMU_OPTION_loadvm,
     QEMU_OPTION_full_screen,
+    QEMU_OPTION_no_quit,
     QEMU_OPTION_pidfile,
     QEMU_OPTION_no_kqemu,
     QEMU_OPTION_kernel_kqemu,
@@ -5528,7 +6424,11 @@ enum {
     QEMU_OPTION_smp,
     QEMU_OPTION_vnc,
     QEMU_OPTION_no_acpi,
-
+    QEMU_OPTION_no_reboot,
+    QEMU_OPTION_daemonize,
+    QEMU_OPTION_option_rom,
+    QEMU_OPTION_semihosting
+    ,
     QEMU_OPTION_d,
     QEMU_OPTION_vcpus,
     QEMU_OPTION_timeoffset,
@@ -5546,6 +6446,7 @@ typedef struct QEMUOption {
 
 const QEMUOption qemu_options[] = {
     { "h", 0, QEMU_OPTION_h },
+    { "help", 0, QEMU_OPTION_h },
 
     { "M", HAS_ARG, QEMU_OPTION_M },
     { "fda", HAS_ARG, QEMU_OPTION_fda },
@@ -5607,6 +6508,9 @@ const QEMUOption qemu_options[] = {
     { "parallel", 1, QEMU_OPTION_parallel },
     { "loadvm", HAS_ARG, QEMU_OPTION_loadvm },
     { "full-screen", 0, QEMU_OPTION_full_screen },
+#ifdef CONFIG_SDL
+    { "no-quit", 0, QEMU_OPTION_no_quit },
+#endif
     { "pidfile", HAS_ARG, QEMU_OPTION_pidfile },
     { "win2k-hack", 0, QEMU_OPTION_win2k_hack },
     { "usbdevice", HAS_ARG, QEMU_OPTION_usbdevice },
@@ -5615,11 +6519,17 @@ const QEMUOption qemu_options[] = {
     { "vncviewer", 0, QEMU_OPTION_vncviewer },
     { "vncunused", 0, QEMU_OPTION_vncunused },
     { "vnclisten", HAS_ARG, QEMU_OPTION_vnclisten },
-    
+
     /* temporary options */
     { "usb", 0, QEMU_OPTION_usb },
     { "cirrusvga", 0, QEMU_OPTION_cirrusvga },
     { "no-acpi", 0, QEMU_OPTION_no_acpi },
+    { "no-reboot", 0, QEMU_OPTION_no_reboot },
+    { "daemonize", 0, QEMU_OPTION_daemonize },
+    { "option-rom", HAS_ARG, QEMU_OPTION_option_rom },
+#if defined(TARGET_ARM)
+    { "semihosting", 0, QEMU_OPTION_semihosting },
+#endif
     
     { "d", HAS_ARG, QEMU_OPTION_d },
     { "vcpus", 1, QEMU_OPTION_vcpus },
@@ -5686,6 +6596,7 @@ void register_machines(void)
     qemu_register_machine(&prep_machine);
 #elif defined(TARGET_MIPS)
     qemu_register_machine(&mips_machine);
+    qemu_register_machine(&mips_malta_machine);
 #elif defined(TARGET_SPARC)
 #ifdef TARGET_SPARC64
     qemu_register_machine(&sun4u_machine);
@@ -5697,6 +6608,7 @@ void register_machines(void)
     qemu_register_machine(&integratorcp1026_machine);
     qemu_register_machine(&versatilepb_machine);
     qemu_register_machine(&versatileab_machine);
+    qemu_register_machine(&realview_machine);
 #elif defined(TARGET_SH4)
     qemu_register_machine(&shix_machine);
 #else
@@ -6063,7 +6975,6 @@ int main(int argc, char **argv)
     const char *kernel_filename, *kernel_cmdline;
     DisplayState *ds = &display_state;
     int cyls, heads, secs, translation;
-    int start_emulation = 1;
     char net_clients[MAX_NET_CLIENTS][256];
     int nb_net_clients;
     int optind;
@@ -6078,6 +6989,7 @@ int main(int argc, char **argv)
     QEMUMachine *machine;
     char usb_devices[MAX_USB_CMDLINE][128];
     int usb_devices_index;
+    int fds[2];
     unsigned long ioreq_pfn;
     extern void *shared_page;
     extern void *buffered_io_page;
@@ -6197,6 +7109,9 @@ int main(int argc, char **argv)
             const QEMUOption *popt;
 
             optind++;
+            /* Treat --foo the same as -foo.  */
+            if (r[1] == '-')
+                r++;
             popt = qemu_options;
             for(;;) {
                 if (!popt->name) {
@@ -6312,13 +7227,13 @@ int main(int argc, char **argv)
 #endif /* !CONFIG_DM */
             case QEMU_OPTION_boot:
                 boot_device = strdup(optarg);
-                if (strspn(boot_device, "acd"
+                if (strspn(boot_device, "a"
 #if defined(TARGET_SPARC) || defined(TARGET_I386)
-                           "n"
+                   // Network boot
+                   "n"
 #endif
-                        ) != strlen(boot_device)) {
-                    fprintf(stderr, "qemu: invalid boot device in '%s'\n",
-                            boot_device);
+                   "cd") != strlen(boot_device)) {
+                    fprintf(stderr, "qemu: invalid boot device in '%s'\n", boot_device);
                     exit(1);
                 }
                 break;
@@ -6414,7 +7329,7 @@ int main(int argc, char **argv)
                 bios_dir = optarg;
                 break;
             case QEMU_OPTION_S:
-                start_emulation = 0;
+                autostart = 0;
                 break;
            case QEMU_OPTION_k:
                keyboard_layout = optarg;
@@ -6489,6 +7404,11 @@ int main(int argc, char **argv)
             case QEMU_OPTION_full_screen:
                 full_screen = 1;
                 break;
+#ifdef CONFIG_SDL
+            case QEMU_OPTION_no_quit:
+                no_quit = 1;
+                break;
+#endif
             case QEMU_OPTION_pidfile:
                 create_pidfile(optarg);
                 break;
@@ -6527,15 +7447,28 @@ int main(int argc, char **argv)
                 }
                 break;
            case QEMU_OPTION_vnc:
-               vnc_display = atoi(optarg);
-               if (vnc_display < 0) {
-                   fprintf(stderr, "Invalid VNC display\n");
-                   exit(1);
-               }
+               vnc_display = optarg;
                break;
             case QEMU_OPTION_no_acpi:
                 acpi_enabled = 0;
                 break;
+            case QEMU_OPTION_no_reboot:
+                no_reboot = 1;
+                break;
+           case QEMU_OPTION_daemonize:
+               daemonize = 1;
+               break;
+           case QEMU_OPTION_option_rom:
+               if (nb_option_roms >= MAX_OPTION_ROMS) {
+                   fprintf(stderr, "Too many option ROMs\n");
+                   exit(1);
+               }
+               option_rom[nb_option_roms] = optarg;
+               nb_option_roms++;
+               break;
+            case QEMU_OPTION_semihosting:
+                semihosting_enabled = 1;
+                break;
             case QEMU_OPTION_domainname:
                 strncat(domain_name, optarg, sizeof(domain_name) - 20);
                 break;
@@ -6558,8 +7491,6 @@ int main(int argc, char **argv)
                 break;
             case QEMU_OPTION_vncunused:
                 vncunused++;
-                if (vnc_display == -1)
-                    vnc_display = 0;
                 break;
             case QEMU_OPTION_vnclisten:
                 parse_host(&vnclisten_addr, optarg);
@@ -6568,6 +7499,54 @@ int main(int argc, char **argv)
         }
     }
 
+#ifndef _WIN32
+    if (daemonize && !nographic && vnc_display == NULL && vncunused == 0) {
+       fprintf(stderr, "Can only daemonize if using -nographic or -vnc\n");
+       daemonize = 0;
+    }
+
+    if (daemonize) {
+       pid_t pid;
+
+       if (pipe(fds) == -1)
+           exit(1);
+
+       pid = fork();
+       if (pid > 0) {
+           uint8_t status;
+           ssize_t len;
+
+           close(fds[1]);
+
+       again:
+           len = read(fds[0], &status, 1);
+           if (len == -1 && (errno == EINTR))
+               goto again;
+           
+           if (len != 1 || status != 0)
+               exit(1);
+           else
+               exit(0);
+       } else if (pid < 0)
+           exit(1);
+
+       setsid();
+
+       pid = fork();
+       if (pid > 0)
+           exit(0);
+       else if (pid < 0)
+           exit(1);
+
+       umask(027);
+       chdir("/");
+
+        signal(SIGTSTP, SIG_IGN);
+        signal(SIGTTOU, SIG_IGN);
+        signal(SIGTTIN, SIG_IGN);
+    }
+#endif
+
 #ifdef CONFIG_DM
     bdrv_init();
     xenstore_parse_domain_config(domid);
@@ -6578,29 +7557,28 @@ int main(int argc, char **argv)
         kqemu_allowed = 0;
 #endif
     linux_boot = (kernel_filename != NULL);
-        
+
 #ifndef CONFIG_DM
-    if (!linux_boot && 
+    if (!linux_boot &&
         hd_filename[0] == '\0' && 
         (cdrom_index >= 0 && hd_filename[cdrom_index] == '\0') &&
         fd_filename[0] == '\0')
         help();
-    
-#if 0
-    /* boot to cd by default if no hard disk */
+
+    /* boot to floppy or the default cd if no hard disk defined yet */
     if (hd_filename[0] == '\0' && boot_device == 'c') {
         if (fd_filename[0] != '\0')
             boot_device = 'a';
         else
             boot_device = 'd';
     }
-#endif
 #endif /* !CONFIG_DM */
 
     setvbuf(stdout, NULL, _IOLBF, 0);
     
     init_timers();
     init_timer_alarm();
+    qemu_aio_init();
 
 #ifdef _WIN32
     socket_init();
@@ -6623,6 +7601,30 @@ int main(int argc, char **argv)
             exit(1);
     }
 
+#ifndef CONFIG_DM
+#ifdef TARGET_I386
+    if (boot_device == 'n') {
+       for (i = 0; i < nb_nics; i++) {
+           const char *model = nd_table[i].model;
+           char buf[1024];
+           if (model == NULL)
+               model = "ne2k_pci";
+           snprintf(buf, sizeof(buf), "%s/pxe-%s.bin", bios_dir, model);
+           if (get_image_size(buf) > 0) {
+               option_rom[nb_option_roms] = strdup(buf);
+               nb_option_roms++;
+               break;
+           }
+       }
+       if (i == nb_nics) {
+           fprintf(stderr, "No valid PXE rom found for network device\n");
+           exit(1);
+       }
+       boot_device = 'c'; /* to prevent confusion by the BIOS */
+    }
+#endif
+#endif /* !CONFIG_DM */
+
 #if defined (__ia64__)
     if (ram_size > MMIO_START)
         ram_size += 1 * MEM_G; /* skip 3G-4G MMIO, LEGACY_IO_SPACE etc. */
@@ -6631,6 +7633,17 @@ int main(int argc, char **argv)
     /* init the memory */
     phys_ram_size = ram_size + vga_ram_size + bios_size;
 
+#ifndef CONFIG_DM
+    for (i = 0; i < nb_option_roms; i++) {
+       int ret = get_image_size(option_rom[i]);
+       if (ret == -1) {
+           fprintf(stderr, "Could not load option rom '%s'\n", option_rom[i]);
+           exit(1);
+       }
+       phys_ram_size += ret;
+    }
+#endif /* !CONFIG_DM */
+
 #ifdef CONFIG_DM
 
     xc_handle = xc_interface_open();
@@ -6731,7 +7744,7 @@ int main(int argc, char **argv)
                 snprintf(buf, sizeof(buf), "hd%c", i + 'a');
                 bs_table[i] = bdrv_new(buf);
             }
-            if (bdrv_open(bs_table[i], hd_filename[i], snapshot) < 0) {
+            if (bdrv_open(bs_table[i], hd_filename[i], snapshot ? BDRV_O_SNAPSHOT : 0) < 0) {
                 fprintf(stderr, "qemu: could not open hard disk image '%s'\n",
                         hd_filename[i]);
                 exit(1);
@@ -6757,7 +7770,8 @@ int main(int argc, char **argv)
                 bdrv_set_type_hint(fd_table[i], BDRV_TYPE_FLOPPY);
             }
             if (fd_filename[i] != '\0') {
-                if (bdrv_open(fd_table[i], fd_filename[i], snapshot) < 0) {
+                if (bdrv_open(fd_table[i], fd_filename[i],
+                              snapshot ? BDRV_O_SNAPSHOT : 0) < 0) {
                     fprintf(stderr, "qemu: could not open floppy disk image '%s'\n",
                             fd_filename[i]);
                     exit(1);
@@ -6766,8 +7780,8 @@ int main(int argc, char **argv)
         }
     }
 
-    register_savevm("timer", 0, 1, timer_save, timer_load, NULL);
-    register_savevm("ram", 0, 1, ram_save, ram_load, NULL);
+    register_savevm("timer", 0, 2, timer_save, timer_load, NULL);
+    register_savevm("ram", 0, 2, ram_save, ram_load, NULL);
 
     init_ioports();
 
@@ -6778,11 +7792,13 @@ int main(int argc, char **argv)
     /* terminal init */
     if (nographic) {
         dumb_display_init(ds);
-    } else if (vnc_display != -1) {
-       vnc_display = vnc_display_init(ds, vnc_display, vncunused, &vnclisten_addr);
+    } else if (vnc_display != NULL || vncunused != 0) {
+       int vnc_display_port;
+       vnc_display_port = vnc_display_init(ds, vnc_display, vncunused,
+                                           &vnclisten_addr);
        if (vncviewer)
-           vnc_start_viewer(vnc_display);
-       xenstore_write_vncport(vnc_display);
+           vnc_start_viewer(vnc_display_port);
+       xenstore_write_vncport(vnc_display_port);
     } else {
 #if defined(CONFIG_SDL)
         sdl_display_init(ds, full_screen);
@@ -6802,12 +7818,13 @@ int main(int argc, char **argv)
     monitor_init(monitor_hd, !nographic);
 
     for(i = 0; i < MAX_SERIAL_PORTS; i++) {
-        if (serial_devices[i][0] != '\0') {
+        const char *devname = serial_devices[i];
+        if (devname[0] != '\0' && strcmp(devname, "none")) {
             char buf[16];
-            serial_hds[i] = qemu_chr_open(serial_devices[i]);
+            serial_hds[i] = qemu_chr_open(devname);
             if (!serial_hds[i]) {
                 fprintf(stderr, "qemu: could not open serial device '%s'\n", 
-                        serial_devices[i]);
+                        devname);
                 exit(1);
             }
             snprintf(buf, sizeof(buf), "/serial/%d", i);
@@ -6815,23 +7832,24 @@ int main(int argc, char **argv)
             if (i == 0) /* serial 0 is also called the console */
                 store_dev_info(serial_devices[i], domid,
                                serial_hds[i], "/console");
-            if (!strcmp(serial_devices[i], "vc"))
+            if (!strcmp(devname, "vc"))
                 qemu_chr_printf(serial_hds[i], "serial%d console\r\n", i);
         }
     }
 
     for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
-        if (parallel_devices[i][0] != '\0') {
+        const char *devname = parallel_devices[i];
+        if (devname[0] != '\0' && strcmp(devname, "none")) {
             char buf[16];
-            parallel_hds[i] = qemu_chr_open(parallel_devices[i]);
+            parallel_hds[i] = qemu_chr_open(devname);
             if (!parallel_hds[i]) {
                 fprintf(stderr, "qemu: could not open parallel device '%s'\n", 
-                        parallel_devices[i]);
+                        devname);
                 exit(1);
             }
             snprintf(buf, sizeof(buf), "/parallel/%d", i);
             store_dev_info(parallel_devices[i], domid, parallel_hds[i], buf);
-            if (!strcmp(parallel_devices[i], "vc"))
+            if (!strcmp(devname, "vc"))
                 qemu_chr_printf(parallel_hds[i], "parallel%d console\r\n", i);
         }
     }
@@ -6854,33 +7872,57 @@ int main(int argc, char **argv)
         }
     }
 
-    if (vnc_display == -1) {
+    if (vnc_display == NULL && vncunused == 0) {
         gui_timer = qemu_new_timer(rt_clock, gui_update, NULL);
         qemu_mod_timer(gui_timer, qemu_get_clock(rt_clock));
     }
 
 #ifdef CONFIG_GDBSTUB
     if (use_gdbstub) {
-        if (gdbserver_start(gdbstub_port) < 0) {
-            fprintf(stderr, "Could not open gdbserver socket on port %d\n", 
+        /* XXX: use standard host:port notation and modify options
+           accordingly. */
+        if (gdbserver_start_port(gdbstub_port) < 0) {
+            fprintf(stderr, "qemu: could not open gdbstub device on port '%d'\n",
                     gdbstub_port);
             exit(1);
-        } else {
-            printf("Waiting gdb connection on port %d\n", gdbstub_port);
         }
     } else 
 #endif
     if (loadvm)
-        qemu_loadvm(loadvm);
+        do_loadvm(loadvm);
 
     {
         /* XXX: simplify init */
         read_passwords();
-        if (start_emulation) {
+        if (autostart) {
             vm_start();
         }
     }
 
+    if (daemonize) {
+       uint8_t status = 0;
+       ssize_t len;
+       int fd;
+
+    again1:
+       len = write(fds[1], &status, 1);
+       if (len == -1 && (errno == EINTR))
+           goto again1;
+
+       if (len != 1)
+           exit(1);
+
+       fd = open("/dev/null", O_RDWR);
+       if (fd == -1)
+           exit(1);
+
+       dup2(fd, 0);
+       dup2(fd, 1);
+       dup2(fd, 2);
+
+       close(fd);
+    }
+
     /* register signal for the suspend request when save */
     {
         struct sigaction act;
index 7f90b2cb70b596dc91ce96628f84c020ade62895..4ca91e4dc77f612f93fc82cf56df5e91c0b6233a 100644 (file)
 #define O_BINARY 0
 #endif
 
+#ifndef ENOMEDIUM
+#define ENOMEDIUM ENODEV
+#endif
+
 #ifdef _WIN32
 #include <windows.h>
 #define fsync _commit
@@ -84,7 +88,6 @@ static inline char *realpath(const char *path, char *resolved_path)
 
 #include "audio/audio.h"
 #include "cpu.h"
-#include "gdbstub.h"
 
 #endif /* !defined(QEMU_TOOL) */
 
@@ -102,6 +105,12 @@ static inline char *realpath(const char *path, char *resolved_path)
 #define MAX(a, b) (((a) > (b)) ? (a) : (b))
 #endif
 
+/* cutils.c */
+void pstrcpy(char *buf, int buf_size, const char *str);
+char *pstrcat(char *buf, int buf_size, const char *s);
+int strstart(const char *str, const char *val, const char **ptr);
+int stristart(const char *str, const char *val, const char **ptr);
+
 /* vl.c */
 uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c);
 
@@ -109,10 +118,6 @@ void hw_error(const char *fmt, ...);
 
 extern const char *bios_dir;
 
-void pstrcpy(char *buf, int buf_size, const char *str);
-char *pstrcat(char *buf, int buf_size, const char *s);
-int strstart(const char *str, const char *val, const char **ptr);
-
 extern int vm_running;
 
 typedef struct vm_change_state_entry VMChangeStateEntry;
@@ -194,12 +199,19 @@ extern int win2k_install_hack;
 extern int usb_enabled;
 extern int acpi_enabled;
 extern int smp_cpus;
+extern int no_quit;
+extern int semihosting_enabled;
+extern int autostart;
+
+#define MAX_OPTION_ROMS 16
+extern const char *option_rom[MAX_OPTION_ROMS];
+extern int nb_option_roms;
 
 /* XXX: make it dynamic */
 #if defined (TARGET_PPC) || defined (TARGET_SPARC64)
 #define BIOS_SIZE ((512 + 32) * 1024)
 #elif defined(TARGET_MIPS)
-#define BIOS_SIZE (128 * 1024)
+#define BIOS_SIZE (4 * 1024 * 1024)
 #else
 #define BIOS_SIZE ((256 + 64) * 1024)
 #endif
@@ -213,13 +225,29 @@ extern int smp_cpus;
 typedef void QEMUPutKBDEvent(void *opaque, int keycode);
 typedef void QEMUPutMouseEvent(void *opaque, int dx, int dy, int dz, int buttons_state);
 
+typedef struct QEMUPutMouseEntry {
+    QEMUPutMouseEvent *qemu_put_mouse_event;
+    void *qemu_put_mouse_event_opaque;
+    int qemu_put_mouse_event_absolute;
+    char *qemu_put_mouse_event_name;
+
+    /* used internally by qemu for handling mice */
+    struct QEMUPutMouseEntry *next;
+} QEMUPutMouseEntry;
+
 void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque);
-void qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, void *opaque, int absolute);
+QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func,
+                                                void *opaque, int absolute,
+                                                const char *name);
+void qemu_remove_mouse_event_handler(QEMUPutMouseEntry *entry);
 
 void kbd_put_keycode(int keycode);
 void kbd_mouse_event(int dx, int dy, int dz, int buttons_state);
 int kbd_mouse_is_absolute(void);
 
+void do_info_mice(void);
+void do_mouse_set(int index);
+
 /* keysym is a unicode code except for special keys (see QEMU_KEY_xxx
    constants) */
 #define QEMU_KEY_ESC1(c) ((c) | 0xe100)
@@ -277,11 +305,13 @@ int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque);
 void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque);
 #endif
 
+typedef struct QEMUBH QEMUBH;
+
 /* character device */
 
 #define CHR_EVENT_BREAK 0 /* serial break char */
 #define CHR_EVENT_FOCUS 1 /* focus to this terminal (modal input needed) */
-
+#define CHR_EVENT_RESET 2 /* new connection established */
 
 
 #define CHR_IOCTL_SERIAL_SET_PARAMS   1
@@ -304,24 +334,31 @@ typedef void IOEventHandler(void *opaque, int event);
 
 typedef struct CharDriverState {
     int (*chr_write)(struct CharDriverState *s, const uint8_t *buf, int len);
-    void (*chr_add_read_handler)(struct CharDriverState *s, 
-                                 IOCanRWHandler *fd_can_read, 
-                                 IOReadHandler *fd_read, void *opaque);
+    void (*chr_update_read_handler)(struct CharDriverState *s);
     int (*chr_ioctl)(struct CharDriverState *s, int cmd, void *arg);
     IOEventHandler *chr_event;
+    IOCanRWHandler *chr_can_read;
+    IOReadHandler *chr_read;
+    void *handler_opaque;
     void (*chr_send_event)(struct CharDriverState *chr, int event);
     void (*chr_close)(struct CharDriverState *chr);
     void *opaque;
+    QEMUBH *bh;
 } CharDriverState;
 
+CharDriverState *qemu_chr_open(const char *filename);
 void qemu_chr_printf(CharDriverState *s, const char *fmt, ...);
 int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len);
 void qemu_chr_send_event(CharDriverState *s, int event);
-void qemu_chr_add_read_handler(CharDriverState *s, 
-                               IOCanRWHandler *fd_can_read, 
-                               IOReadHandler *fd_read, void *opaque);
-void qemu_chr_add_event_handler(CharDriverState *s, IOEventHandler *chr_event);
+void qemu_chr_add_handlers(CharDriverState *s, 
+                           IOCanRWHandler *fd_can_read, 
+                           IOReadHandler *fd_read,
+                           IOEventHandler *fd_event,
+                           void *opaque);
 int qemu_chr_ioctl(CharDriverState *s, int cmd, void *arg);
+void qemu_chr_reset(CharDriverState *s);
+int qemu_chr_can_read(CharDriverState *s);
+void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len);
 
 /* consoles */
 
@@ -391,7 +428,6 @@ void do_info_network(void);
 
 /* TAP win32 */
 int tap_win32_init(VLANState *vlan, const char *ifname);
-void tap_win32_poll(void);
 
 /* NIC info */
 
@@ -441,8 +477,11 @@ void cpu_disable_ticks(void);
 
 /* VM Load/Save */
 
-typedef FILE QEMUFile;
+typedef struct QEMUFile QEMUFile;
 
+QEMUFile *qemu_fopen(const char *filename, const char *mode);
+void qemu_fflush(QEMUFile *f);
+void qemu_fclose(QEMUFile *f);
 void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size);
 void qemu_put_byte(QEMUFile *f, int v);
 void qemu_put_be16(QEMUFile *f, unsigned int v);
@@ -512,8 +551,6 @@ int64_t qemu_fseek(QEMUFile *f, int64_t pos, int whence);
 typedef void SaveStateHandler(QEMUFile *f, void *opaque);
 typedef int LoadStateHandler(QEMUFile *f, void *opaque, int version_id);
 
-int qemu_loadvm(const char *filename);
-int qemu_savevm(const char *filename);
 int register_savevm(const char *idstr, 
                     int instance_id, 
                     int version_id,
@@ -526,11 +563,26 @@ void qemu_put_timer(QEMUFile *f, QEMUTimer *ts);
 void cpu_save(QEMUFile *f, void *opaque);
 int cpu_load(QEMUFile *f, void *opaque, int version_id);
 
+void do_savevm(const char *name);
+void do_loadvm(const char *name);
+void do_delvm(const char *name);
+void do_info_snapshots(void);
+
+/* bottom halves */
+typedef void QEMUBHFunc(void *opaque);
+
+QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque);
+void qemu_bh_schedule(QEMUBH *bh);
+void qemu_bh_cancel(QEMUBH *bh);
+void qemu_bh_delete(QEMUBH *bh);
+int qemu_bh_poll(void);
+
 /* block.c */
 typedef struct BlockDriverState BlockDriverState;
 typedef struct BlockDriver BlockDriver;
 
 extern BlockDriver bdrv_raw;
+extern BlockDriver bdrv_host_device;
 extern BlockDriver bdrv_cow;
 extern BlockDriver bdrv_qcow;
 extern BlockDriver bdrv_vmdk;
@@ -539,6 +591,35 @@ extern BlockDriver bdrv_dmg;
 extern BlockDriver bdrv_bochs;
 extern BlockDriver bdrv_vpc;
 extern BlockDriver bdrv_vvfat;
+extern BlockDriver bdrv_qcow2;
+
+typedef struct BlockDriverInfo {
+    /* in bytes, 0 if irrelevant */
+    int cluster_size; 
+    /* offset at which the VM state can be saved (0 if not possible) */
+    int64_t vm_state_offset; 
+} BlockDriverInfo;
+
+typedef struct QEMUSnapshotInfo {
+    char id_str[128]; /* unique snapshot id */
+    /* the following fields are informative. They are not needed for
+       the consistency of the snapshot */
+    char name[256]; /* user choosen name */
+    uint32_t vm_state_size; /* VM state info size */
+    uint32_t date_sec; /* UTC date of the snapshot */
+    uint32_t date_nsec;
+    uint64_t vm_clock_nsec; /* VM clock relative to boot */
+} QEMUSnapshotInfo;
+
+#define BDRV_O_RDONLY      0x0000
+#define BDRV_O_RDWR        0x0002
+#define BDRV_O_ACCESS      0x0003
+#define BDRV_O_CREAT       0x0004 /* create an empty file */
+#define BDRV_O_SNAPSHOT    0x0008 /* open the file read only and save writes in a snapshot */
+#define BDRV_O_FILE        0x0010 /* open as a raw file (do not try to
+                                     use a disk image format on top of
+                                     it (default for
+                                     bdrv_file_open()) */
 
 void bdrv_init(void);
 BlockDriver *bdrv_find_format(const char *format_name);
@@ -547,26 +628,54 @@ int bdrv_create(BlockDriver *drv,
                 const char *backing_file, int flags);
 BlockDriverState *bdrv_new(const char *device_name);
 void bdrv_delete(BlockDriverState *bs);
-int bdrv_open(BlockDriverState *bs, const char *filename, int snapshot);
-int bdrv_open2(BlockDriverState *bs, const char *filename, int snapshot,
+int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags);
+int bdrv_open(BlockDriverState *bs, const char *filename, int flags);
+int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
                BlockDriver *drv);
 void bdrv_close(BlockDriverState *bs);
 int bdrv_read(BlockDriverState *bs, int64_t sector_num, 
               uint8_t *buf, int nb_sectors);
 int bdrv_write(BlockDriverState *bs, int64_t sector_num, 
                const uint8_t *buf, int nb_sectors);
+int bdrv_pread(BlockDriverState *bs, int64_t offset, 
+               void *buf, int count);
+int bdrv_pwrite(BlockDriverState *bs, int64_t offset, 
+                const void *buf, int count);
+int bdrv_truncate(BlockDriverState *bs, int64_t offset);
+int64_t bdrv_getlength(BlockDriverState *bs);
 void bdrv_get_geometry(BlockDriverState *bs, int64_t *nb_sectors_ptr);
 int bdrv_commit(BlockDriverState *bs);
 void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size);
+/* async block I/O */
+typedef struct BlockDriverAIOCB BlockDriverAIOCB;
+typedef void BlockDriverCompletionFunc(void *opaque, int ret);
+
+BlockDriverAIOCB *bdrv_aio_read(BlockDriverState *bs, int64_t sector_num,
+                                uint8_t *buf, int nb_sectors,
+                                BlockDriverCompletionFunc *cb, void *opaque);
+BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, int64_t sector_num,
+                                 const uint8_t *buf, int nb_sectors,
+                                 BlockDriverCompletionFunc *cb, void *opaque);
+void bdrv_aio_cancel(BlockDriverAIOCB *acb);
+
+void qemu_aio_init(void);
+void qemu_aio_poll(void);
+void qemu_aio_flush(void);
+void qemu_aio_wait_start(void);
+void qemu_aio_wait(void);
+void qemu_aio_wait_end(void);
+
 /* Ensure contents are flushed to disk.  */
 void bdrv_flush(BlockDriverState *bs);
 
 #define BDRV_TYPE_HD     0
 #define BDRV_TYPE_CDROM  1
 #define BDRV_TYPE_FLOPPY 2
-#define BIOS_ATA_TRANSLATION_AUTO 0
-#define BIOS_ATA_TRANSLATION_NONE 1
-#define BIOS_ATA_TRANSLATION_LBA  2
+#define BIOS_ATA_TRANSLATION_AUTO   0
+#define BIOS_ATA_TRANSLATION_NONE   1
+#define BIOS_ATA_TRANSLATION_LBA    2
+#define BIOS_ATA_TRANSLATION_LARGE  3
+#define BIOS_ATA_TRANSLATION_RECHS  4
 
 void bdrv_set_geometry_hint(BlockDriverState *bs, 
                             int cyls, int heads, int secs);
@@ -579,8 +688,10 @@ int bdrv_get_translation_hint(BlockDriverState *bs);
 int bdrv_is_removable(BlockDriverState *bs);
 int bdrv_is_read_only(BlockDriverState *bs);
 int bdrv_is_inserted(BlockDriverState *bs);
+int bdrv_media_changed(BlockDriverState *bs);
 int bdrv_is_locked(BlockDriverState *bs);
 void bdrv_set_locked(BlockDriverState *bs, int locked);
+void bdrv_eject(BlockDriverState *bs, int eject_flag);
 void bdrv_set_change_cb(BlockDriverState *bs, 
                         void (*change_cb)(void *opaque), void *opaque);
 void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size);
@@ -592,10 +703,26 @@ int bdrv_set_key(BlockDriverState *bs, const char *key);
 void bdrv_iterate_format(void (*it)(void *opaque, const char *name), 
                          void *opaque);
 const char *bdrv_get_device_name(BlockDriverState *bs);
-
-int qcow_get_cluster_size(BlockDriverState *bs);
-int qcow_compress_cluster(BlockDriverState *bs, int64_t sector_num,
-                          const uint8_t *buf);
+int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num, 
+                          const uint8_t *buf, int nb_sectors);
+int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
+
+void bdrv_get_backing_filename(BlockDriverState *bs, 
+                               char *filename, int filename_size);
+int bdrv_snapshot_create(BlockDriverState *bs, 
+                         QEMUSnapshotInfo *sn_info);
+int bdrv_snapshot_goto(BlockDriverState *bs, 
+                       const char *snapshot_id);
+int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id);
+int bdrv_snapshot_list(BlockDriverState *bs, 
+                       QEMUSnapshotInfo **psn_info);
+char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn);
+
+char *get_human_readable_size(char *buf, int buf_size, int64_t size);
+int path_is_absolute(const char *path);
+void path_combine(char *dest, int dest_size,
+                  const char *base_path,
+                  const char *filename);
 
 #ifndef QEMU_TOOL
 
@@ -630,6 +757,8 @@ int register_ioport_write(int start, int length, int size,
                           IOPortWriteFunc *func, void *opaque);
 void isa_unassign_ioport(int start, int length);
 
+void isa_mmio_init(target_phys_addr_t base, target_phys_addr_t size);
+
 /* PCI bus */
 
 extern target_phys_addr_t pci_mem_base;
@@ -689,6 +818,9 @@ struct PCIDevice {
     PCIConfigWriteFunc *config_write;
     /* ??? This is a PC-specific hack, and should be removed.  */
     int irq_index;
+
+    /* Current IRQ levels.  Used internally by the generic PCI code.  */
+    int irq_state[4];
 };
 
 PCIDevice *pci_register_device(PCIBus *bus, const char *name,
@@ -706,20 +838,23 @@ uint32_t pci_default_read_config(PCIDevice *d,
                                  uint32_t address, int len);
 void pci_default_write_config(PCIDevice *d, 
                               uint32_t address, uint32_t val, int len);
-void generic_pci_save(QEMUFile* f, void *opaque);
-int generic_pci_load(QEMUFile* f, void *opaque, int version_id);
+void pci_device_save(PCIDevice *s, QEMUFile *f);
+int pci_device_load(PCIDevice *s, QEMUFile *f);
 
-typedef void (*pci_set_irq_fn)(PCIDevice *pci_dev, void *pic,
-                               int irq_num, int level);
-PCIBus *pci_register_bus(pci_set_irq_fn set_irq, void *pic, int devfn_min);
+typedef void (*pci_set_irq_fn)(void *pic, int irq_num, int level);
+typedef int (*pci_map_irq_fn)(PCIDevice *pci_dev, int irq_num);
+PCIBus *pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
+                         void *pic, int devfn_min, int nirq);
 
-void pci_nic_init(PCIBus *bus, NICInfo *nd);
+void pci_nic_init(PCIBus *bus, NICInfo *nd, int devfn);
 void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len);
 uint32_t pci_data_read(void *opaque, uint32_t addr, int len);
 int pci_bus_num(PCIBus *s);
-void pci_for_each_device(void (*fn)(PCIDevice *d));
+void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d));
 
 void pci_info(void);
+PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint32_t id,
+                        pci_map_irq_fn map_irq, const char *name);
 
 /* prep_pci.c */
 PCIBus *pci_prep_init(void);
@@ -734,12 +869,15 @@ PCIBus *pci_pmac_init(void *pic);
 PCIBus *pci_apb_init(target_ulong special_base, target_ulong mem_base,
                      void *pic);
 
-PCIBus *pci_vpb_init(void *pic);
+PCIBus *pci_vpb_init(void *pic, int irq, int realview);
 
 /* piix_pci.c */
-PCIBus *i440fx_init(void);
-int piix3_init(PCIBus *bus);
-void pci_bios_init(void);
+PCIBus *i440fx_init(PCIDevice **pi440fx_state);
+void i440fx_set_smm(PCIDevice *d, int val);
+int piix3_init(PCIBus *bus, int devfn);
+void i440fx_init_memory_mappings(PCIDevice *d);
+
+int piix4_init(PCIBus *bus, int devfn);
 
 /* openpic.c */
 typedef struct openpic_t openpic_t;
@@ -752,6 +890,9 @@ typedef struct HeathrowPICS HeathrowPICS;
 void heathrow_pic_set_irq(void *opaque, int num, int level);
 HeathrowPICS *heathrow_pic_init(int *pmem_index);
 
+/* gt64xxx.c */
+PCIBus *pci_gt64120_init(void *pic);
+
 #ifdef HAS_AUDIO
 struct soundhw {
     const char *name;
@@ -796,9 +937,11 @@ static inline void dpy_resize(DisplayState *s, int w, int h)
     s->dpy_resize(s, w, h);
 }
 
-int vga_initialize(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, 
-                   unsigned long vga_ram_offset, int vga_ram_size,
-                   unsigned long vga_bios_offset, int vga_bios_size);
+int isa_vga_init(DisplayState *ds, uint8_t *vga_ram_base, 
+                 unsigned long vga_ram_offset, int vga_ram_size);
+int pci_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, 
+                 unsigned long vga_ram_offset, int vga_ram_size,
+                 unsigned long vga_bios_offset, int vga_bios_size);
 
 /* cirrus_vga.c */
 void pci_cirrus_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, 
@@ -813,14 +956,18 @@ void sdl_display_init(DisplayState *ds, int full_screen);
 void cocoa_display_init(DisplayState *ds, int full_screen);
 
 /* vnc.c */
-int vnc_display_init(DisplayState *ds, int display, int find_unused, struct sockaddr_in *addr);
+int vnc_display_init(DisplayState *ds, const char *display, int find_unused, struct sockaddr_in *iaddr);
+void do_info_vnc(void);
 int vnc_start_viewer(int port);
 
+/* x_keymap.c */
+extern uint8_t _translate_keycode(const int key);
+
 /* ide.c */
 #define MAX_DISKS 4
 #define MAX_SCSI_DISKS 7
 
-extern BlockDriverState *bs_table[MAX_DISKS + MAX_SCSI_DISKS];
+extern BlockDriverState *bs_table[MAX_DISKS + MAX_SCSI_DISKS + 1];
 
 void isa_ide_init(int iobase, int iobase2, int irq,
                   BlockDriverState *hd0, BlockDriverState *hd1);
@@ -829,7 +976,6 @@ void pci_cmd646_ide_init(PCIBus *bus, BlockDriverState **hd_table,
 void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn);
 int pmac_ide_init (BlockDriverState **hd_table,
                    SetIRQFunc *set_irq, void *irq_opaque, int irq);
-void ide_stop_dma_thread(void);
 
 /* cdrom.c */
 int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track);
@@ -874,15 +1020,18 @@ int fdctrl_get_drive_type(fdctrl_t *fdctrl, int drive_num);
 /* ne2000.c */
 
 void isa_ne2000_init(int base, int irq, NICInfo *nd);
-void pci_ne2000_init(PCIBus *bus, NICInfo *nd);
+void pci_ne2000_init(PCIBus *bus, NICInfo *nd, int devfn);
 
 /* rtl8139.c */
 
-void pci_rtl8139_init(PCIBus *bus, NICInfo *nd);
+void pci_rtl8139_init(PCIBus *bus, NICInfo *nd, int devfn);
 
 /* pcnet.c */
 
-void pci_pcnet_init(PCIBus *bus, NICInfo *nd);
+void pci_pcnet_init(PCIBus *bus, NICInfo *nd, int devfn);
+void pcnet_h_reset(void *opaque);
+void *lance_init(NICInfo *nd, uint32_t leaddr, void *dma_opaque);
+
 
 /* pckbd.c */
 
@@ -951,11 +1100,17 @@ int pit_get_out(PITState *pit, int channel, int64_t current_time);
 void pcspk_init(PITState *);
 int pcspk_audio_init(AudioState *);
 
+#include "hw/smbus.h"
+
 /* acpi.c */
 extern int acpi_enabled;
 void piix4_pm_init(PCIBus *bus, int devfn);
+void piix4_smbus_register_device(SMBusDevice *dev, uint8_t addr);
 void acpi_bios_init(void);
 
+/* smbus_eeprom.c */
+SMBusDevice *smbus_eeprom_device_init(uint8_t addr, uint8_t *buf);
+
 /* tpm_tis.c */
 int has_tpm_device(void);
 void tpm_tis_init(SetIRQFunc *set_irq, void *irq_opaque, int irq);
@@ -979,6 +1134,16 @@ extern QEMUMachine heathrow_machine;
 /* mips_r4k.c */
 extern QEMUMachine mips_machine;
 
+/* mips_malta.c */
+extern QEMUMachine mips_malta_machine;
+
+/* mips_int */
+extern void cpu_mips_irq_request(void *opaque, int irq, int level);
+
+/* mips_timer.c */
+extern void cpu_mips_clock_init(CPUState *);
+extern void cpu_mips_irqctrl_init (void);
+
 /* shix.c */
 extern QEMUMachine shix_machine;
 
@@ -993,15 +1158,25 @@ void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val);
 
 /* sun4m.c */
 extern QEMUMachine sun4m_machine;
-uint32_t iommu_translate(uint32_t addr);
 void pic_set_irq_cpu(int irq, int level, unsigned int cpu);
 
 /* iommu.c */
 void *iommu_init(uint32_t addr);
-uint32_t iommu_translate_local(void *opaque, uint32_t addr);
+void sparc_iommu_memory_rw(void *opaque, target_phys_addr_t addr,
+                                 uint8_t *buf, int len, int is_write);
+static inline void sparc_iommu_memory_read(void *opaque,
+                                           target_phys_addr_t addr,
+                                           uint8_t *buf, int len)
+{
+    sparc_iommu_memory_rw(opaque, addr, buf, len, 0);
+}
 
-/* lance.c */
-void lance_init(NICInfo *nd, int irq, uint32_t leaddr, uint32_t ledaddr);
+static inline void sparc_iommu_memory_write(void *opaque,
+                                            target_phys_addr_t addr,
+                                            uint8_t *buf, int len)
+{
+    sparc_iommu_memory_rw(opaque, addr, buf, len, 1);
+}
 
 /* tcx.c */
 void tcx_init(DisplayState *ds, uint32_t addr, uint8_t *vram_base,
@@ -1033,7 +1208,27 @@ void *slavio_misc_init(uint32_t base, int irq);
 void slavio_set_power_fail(void *opaque, int power_failing);
 
 /* esp.c */
-void esp_init(BlockDriverState **bd, int irq, uint32_t espaddr, uint32_t espdaddr);
+void esp_scsi_attach(void *opaque, BlockDriverState *bd, int id);
+void *esp_init(BlockDriverState **bd, uint32_t espaddr, void *dma_opaque);
+void esp_reset(void *opaque);
+
+/* sparc32_dma.c */
+void *sparc32_dma_init(uint32_t daddr, int espirq, int leirq, void *iommu,
+                       void *intctl);
+void ledma_set_irq(void *opaque, int isr);
+void ledma_memory_read(void *opaque, target_phys_addr_t addr, 
+                       uint8_t *buf, int len, int do_bswap);
+void ledma_memory_write(void *opaque, target_phys_addr_t addr, 
+                        uint8_t *buf, int len, int do_bswap);
+void espdma_raise_irq(void *opaque);
+void espdma_clear_irq(void *opaque);
+void espdma_memory_read(void *opaque, uint8_t *buf, int len);
+void espdma_memory_write(void *opaque, uint8_t *buf, int len);
+void sparc32_dma_set_reset_data(void *opaque, void *esp_opaque,
+                                void *lance_opaque);
+
+/* cs4231.c */
+void cs_init(target_phys_addr_t base, int irq, void *intctl);
 
 /* sun4u.c */
 extern QEMUMachine sun4u_machine;
@@ -1119,17 +1314,29 @@ void do_usb_del(const char *devname);
 void usb_info(void);
 
 /* scsi-disk.c */
+enum scsi_reason {
+    SCSI_REASON_DONE, /* Command complete.  */
+    SCSI_REASON_DATA  /* Transfer complete, more data required.  */
+};
+
 typedef struct SCSIDevice SCSIDevice;
-typedef void (*scsi_completionfn)(void *, uint32_t, int);
+typedef void (*scsi_completionfn)(void *opaque, int reason, uint32_t tag,
+                                  uint32_t arg);
 
 SCSIDevice *scsi_disk_init(BlockDriverState *bdrv,
+                           int tcq,
                            scsi_completionfn completion,
                            void *opaque);
 void scsi_disk_destroy(SCSIDevice *s);
 
 int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf, int lun);
-int scsi_read_data(SCSIDevice *s, uint8_t *data, uint32_t len);
-int scsi_write_data(SCSIDevice *s, uint8_t *data, uint32_t len);
+/* SCSI data transfers are asynchrnonous.  However, unlike the block IO
+   layer the completion routine may be called directly by
+   scsi_{read,write}_data.  */
+void scsi_read_data(SCSIDevice *s, uint32_t tag);
+int scsi_write_data(SCSIDevice *s, uint32_t tag);
+void scsi_cancel_io(SCSIDevice *s, uint32_t tag);
+uint8_t *scsi_get_buf(SCSIDevice *s, uint32_t tag);
 
 /* lsi53c895a.c */
 void lsi_scsi_attach(void *opaque, BlockDriverState *bd, int id);
@@ -1143,6 +1350,9 @@ extern QEMUMachine integratorcp1026_machine;
 extern QEMUMachine versatilepb_machine;
 extern QEMUMachine versatileab_machine;
 
+/* realview.c */
+extern QEMUMachine realview_machine;
+
 /* ps2.c */
 void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg);
 void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg);
@@ -1165,7 +1375,7 @@ void pl011_init(uint32_t base, void *pic, int irq, CharDriverState *chr);
 void pl050_init(uint32_t base, void *pic, int irq, int is_mouse);
 
 /* pl080.c */
-void *pl080_init(uint32_t base, void *pic, int irq);
+void *pl080_init(uint32_t base, void *pic, int irq, int nchannels);
 
 /* pl190.c */
 void *pl190_init(uint32_t base, void *parent, int irq, int fiq);
@@ -1174,9 +1384,15 @@ void *pl190_init(uint32_t base, void *parent, int irq, int fiq);
 void sp804_init(uint32_t base, void *pic, int irq);
 void icp_pit_init(uint32_t base, void *pic, int irq);
 
+/* arm_sysctl.c */
+void arm_sysctl_init(uint32_t base, uint32_t sys_id);
+
+/* arm_gic.c */
+void *arm_gic_init(uint32_t base, void *parent, int parent_irq);
+
 /* arm_boot.c */
 
-void arm_load_kernel(int ram_size, const char *kernel_filename,
+void arm_load_kernel(CPUState *env, int ram_size, const char *kernel_filename,
                      const char *kernel_cmdline, const char *initrd_filename,
                      int board_id);
 
@@ -1211,6 +1427,8 @@ pflash_t *pflash_register (target_ulong base, ram_addr_t off,
                            uint16_t id0, uint16_t id1, 
                            uint16_t id2, uint16_t id3);
 
+#include "gdbstub.h"
+
 #endif /* defined(QEMU_TOOL) */
 
 /* monitor.c */
@@ -1218,6 +1436,7 @@ void monitor_init(CharDriverState *hd, int show_banner);
 void term_puts(const char *str);
 void term_vprintf(const char *fmt, va_list ap);
 void term_printf(const char *fmt, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
+void term_print_filename(const char *filename);
 void term_flush(void);
 void term_print_help(void);
 void monitor_readline(const char *prompt, int is_password,
index d06b47a220fce74097ef4cc5e6485945d704fdc3..1e515de7eb727e6edc31929913f3fcf017ce974d 100644 (file)
@@ -94,6 +94,13 @@ struct VncState
     int depth; /* internal VNC frame buffer byte per pixel */
     int has_resize;
     int has_hextile;
+    int has_pointer_type_change;
+    int absolute;
+    int last_x;
+    int last_y;
+
+    const char *display;
+
     Buffer output;
     Buffer input;
     kbd_layout_t *kbd_layout;
@@ -113,21 +120,39 @@ struct VncState
     int visible_w;
     int visible_h;
 
-    int ctl_keys;               /* Ctrl+Alt starts calibration */
-    int shift_keys;             /* Shift / CapsLock keys */
-    int numlock;
+    /* input */
+    uint8_t modifiers_state[256];
 };
 
+static VncState *vnc_state; /* needed for info vnc */
+
 #define DIRTY_PIXEL_BITS 64
 #define X2DP_DOWN(vs, x) ((x) >> (vs)->dirty_pixel_shift)
 #define X2DP_UP(vs, x) \
   (((x) + (1ULL << (vs)->dirty_pixel_shift) - 1) >> (vs)->dirty_pixel_shift)
 #define DP2X(vs, x) ((x) << (vs)->dirty_pixel_shift)
 
+void do_info_vnc(void)
+{
+    if (vnc_state == NULL)
+       term_printf("VNC server disabled\n");
+    else {
+       term_printf("VNC server active on: ");
+       term_print_filename(vnc_state->display);
+       term_printf("\n");
+
+       if (vnc_state->csock == -1)
+           term_printf("No client connected\n");
+       else
+           term_printf("Client connected\n");
+    }
+}
+
 /* TODO
    1) Get the queue working for IO.
    2) there is some weirdness when using the -S option (the screen is grey
       and not totally invalidated
+   3) resolutions > 1024
 */
 
 static void vnc_write(VncState *vs, const void *data, size_t len);
@@ -231,6 +256,7 @@ static void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
 
 static void vnc_dpy_resize(DisplayState *ds, int w, int h)
 {
+    int size_changed;
     VncState *vs = ds->opaque;
     int o;
 
@@ -249,10 +275,11 @@ static void vnc_dpy_resize(DisplayState *ds, int w, int h)
         ds->depth = vs->depth * 8;
         set_color_table(ds);
     }
+    size_changed = ds->width != w || ds->height != h;
     ds->width = w;
     ds->height = h;
     ds->linesize = w * vs->depth;
-    if (vs->csock != -1 && vs->has_resize) {
+    if (vs->csock != -1 && vs->has_resize && size_changed) {
        vnc_write_u8(vs, 0);  /* msg id */
        vnc_write_u8(vs, 0);
        vnc_write_u16(vs, 1); /* number of rects */
@@ -823,6 +850,19 @@ static void client_cut_text(VncState *vs, size_t len, char *text)
 {
 }
 
+static void check_pointer_type_change(VncState *vs, int absolute)
+{
+    if (vs->has_pointer_type_change && vs->absolute != absolute) {
+       vnc_write_u8(vs, 0);
+       vnc_write_u8(vs, 0);
+       vnc_write_u16(vs, 1);
+       vnc_framebuffer_update(vs, absolute, 0,
+                              vs->ds->width, vs->ds->height, -257);
+       vnc_flush(vs);
+    }
+    vs->absolute = absolute;
+}
+
 static void pointer_event(VncState *vs, int button_mask, int x, int y)
 {
     int buttons = 0;
@@ -838,143 +878,120 @@ static void pointer_event(VncState *vs, int button_mask, int x, int y)
        dz = -1;
     if (button_mask & 0x10)
        dz = 1;
-           
-    if (kbd_mouse_is_absolute()) {
+
+    if (vs->absolute) {
        kbd_mouse_event(x * 0x7FFF / vs->ds->width,
                        y * 0x7FFF / vs->ds->height,
                        dz, buttons);
-    } else {
-       static int last_x = -1;
-       static int last_y = -1;
-
-       if (last_x != -1)
-           kbd_mouse_event(x - last_x, y - last_y, dz, buttons);
+    } else if (vs->has_pointer_type_change) {
+       x -= 0x7FFF;
+       y -= 0x7FFF;
 
-       last_x = x;
-       last_y = y;
+       kbd_mouse_event(x, y, dz, buttons);
+    } else {
+       if (vs->last_x != -1)
+           kbd_mouse_event(x - vs->last_x,
+                           y - vs->last_y,
+                           dz, buttons);
+       vs->last_x = x;
+       vs->last_y = y;
     }
+
+    check_pointer_type_change(vs, kbd_mouse_is_absolute());
 }
 
-static void press_key(VncState *vs, int keycode)
+static void reset_keys(VncState *vs)
 {
-    kbd_put_keycode(keysym2scancode(vs->kbd_layout, keycode) & 0x7f);
-    kbd_put_keycode(keysym2scancode(vs->kbd_layout, keycode) | 0x80);
+    int i;
+    for(i = 0; i < 256; i++) {
+        if (vs->modifiers_state[i]) {
+            if (i & 0x80)
+                kbd_put_keycode(0xe0);
+            kbd_put_keycode(i | 0x80);
+            vs->modifiers_state[i] = 0;
+        }
+    }
 }
 
 static void do_key_event(VncState *vs, int down, uint32_t sym)
 {
-    sym &= 0xFFFF;
+    int keycode;
 
-    if (is_graphic_console()) {
-       int keycode;
-       int numlock;
-
-       keycode = keysym2scancode(vs->kbd_layout, sym);
-       numlock = keysym2numlock(vs->kbd_layout, sym);
-
-        /* If the numlock state needs to change then simulate an additional
-           keypress before sending this one.  This will happen if the user
-           toggles numlock away from the VNC window.
-        */
-       if (numlock == 1) {
-           if (!vs->numlock) {
-               vs->numlock = 1;
-               press_key(vs, XK_Num_Lock);
-           }
-       }
-       else if (numlock == -1) {
-           if (vs->numlock) {
-               vs->numlock = 0;
-               press_key(vs, XK_Num_Lock);
-           }
+    keycode = keysym2scancode(vs->kbd_layout, sym & 0xFFFF);
+    
+    /* QEMU console switch */
+    switch(keycode) {
+    case 0x2a:                          /* Left Shift */
+    case 0x36:                          /* Right Shift */
+    case 0x1d:                          /* Left CTRL */
+    case 0x9d:                          /* Right CTRL */
+    case 0x38:                          /* Left ALT */
+    case 0xb8:                          /* Right ALT */
+        if (down)
+            vs->modifiers_state[keycode] = 1;
+        else
+            vs->modifiers_state[keycode] = 0;
+        break;
+    case 0x02 ... 0x0a: /* '1' to '9' keys */ 
+        if (down && vs->modifiers_state[0x1d] && vs->modifiers_state[0x38]) {
+            /* Reset the modifiers sent to the current console */
+            reset_keys(vs);
+            console_select(keycode - 0x02);
+            return;
         }
-
-       if (keycode & 0x80)
-           kbd_put_keycode(0xe0);
-       if (down)
-           kbd_put_keycode(keycode & 0x7f);
-       else
-           kbd_put_keycode(keycode | 0x80);
-    } else if (down) {
-       int qemu_keysym = 0;
-
-       if (sym <= 128) { /* normal ascii */
-           int shifted = vs->shift_keys == 1 || vs->shift_keys == 2;
-           qemu_keysym = sym;
-           if (sym >= 'a' && sym <= 'z' && shifted)
-               qemu_keysym -= 'a' - 'A';
-       } else {
-           switch (sym) {
-           case XK_Up: qemu_keysym = QEMU_KEY_UP; break;
-           case XK_Down: qemu_keysym = QEMU_KEY_DOWN; break;
-           case XK_Left: qemu_keysym = QEMU_KEY_LEFT; break;
-           case XK_Right: qemu_keysym = QEMU_KEY_RIGHT; break;
-           case XK_Home: qemu_keysym = QEMU_KEY_HOME; break;
-           case XK_End: qemu_keysym = QEMU_KEY_END; break;
-           case XK_Page_Up: qemu_keysym = QEMU_KEY_PAGEUP; break;
-           case XK_Page_Down: qemu_keysym = QEMU_KEY_PAGEDOWN; break;
-           case XK_BackSpace: qemu_keysym = QEMU_KEY_BACKSPACE; break;
-           case XK_Delete: qemu_keysym = QEMU_KEY_DELETE; break;
-           case XK_Return:
-           case XK_Linefeed: qemu_keysym = sym; break;
-           default: break;
-           }
-       }
-       if (qemu_keysym != 0)
-           kbd_put_keysym(qemu_keysym);
+        break;
     }
 
-    if (down) {
-       switch (sym) {
-       case XK_Control_L:
-           vs->ctl_keys |= 1;
-           break;
-
-       case XK_Alt_L:
-           vs->ctl_keys |= 2;
-           break;
-
-       case XK_Shift_L:
-           vs->shift_keys |= 1;
-           break;
-
-       default:
-           break;
-       }
+    if (is_graphic_console()) {
+        if (keycode & 0x80)
+            kbd_put_keycode(0xe0);
+        if (down)
+            kbd_put_keycode(keycode & 0x7f);
+        else
+            kbd_put_keycode(keycode | 0x80);
     } else {
-       switch (sym) {
-       case XK_Control_L:
-           vs->ctl_keys &= ~1;
-           break;
-
-       case XK_Alt_L:
-           vs->ctl_keys &= ~2;
-           break;
-
-       case XK_Shift_L:
-           vs->shift_keys &= ~1;
-           break;
-
-       case XK_Caps_Lock:
-           vs->shift_keys ^= 2;
-           break;
-
-       case XK_Num_Lock:
-           vs->numlock = !vs->numlock;
-           break;
-
-       case XK_1 ... XK_9:
-           if ((vs->ctl_keys & 3) != 3)
-               break;
-
-           console_select(sym - XK_1);
-           if (is_graphic_console()) {
-               /* tell the vga console to redisplay itself */
-               vga_hw_invalidate();
-               vnc_dpy_update(vs->ds, 0, 0, vs->ds->width, vs->ds->height);
-           }
-           break;
-       }
+        /* QEMU console emulation */
+        if (down) {
+            switch (keycode) {
+            case 0x2a:                          /* Left Shift */
+            case 0x36:                          /* Right Shift */
+            case 0x1d:                          /* Left CTRL */
+            case 0x9d:                          /* Right CTRL */
+            case 0x38:                          /* Left ALT */
+            case 0xb8:                          /* Right ALT */
+                break;
+            case 0xc8:
+                kbd_put_keysym(QEMU_KEY_UP);
+                break;
+            case 0xd0:
+                kbd_put_keysym(QEMU_KEY_DOWN);
+                break;
+            case 0xcb:
+                kbd_put_keysym(QEMU_KEY_LEFT);
+                break;
+            case 0xcd:
+                kbd_put_keysym(QEMU_KEY_RIGHT);
+                break;
+            case 0xd3:
+                kbd_put_keysym(QEMU_KEY_DELETE);
+                break;
+            case 0xc7:
+                kbd_put_keysym(QEMU_KEY_HOME);
+                break;
+            case 0xcf:
+                kbd_put_keysym(QEMU_KEY_END);
+                break;
+            case 0xc9:
+                kbd_put_keysym(QEMU_KEY_PAGEUP);
+                break;
+            case 0xd1:
+                kbd_put_keysym(QEMU_KEY_PAGEDOWN);
+                break;
+            default:
+                kbd_put_keysym(sym);
+                break;
+            }
+        }
     }
 }
 
@@ -1013,6 +1030,8 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
 
     vs->has_hextile = 0;
     vs->has_resize = 0;
+    vs->has_pointer_type_change = 0;
+    vs->absolute = -1;
     vs->ds->dpy_copy = NULL;
 
     for (i = n_encodings - 1; i >= 0; i--) {
@@ -1029,10 +1048,15 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
        case -223: /* DesktopResize */
            vs->has_resize = 1;
            break;
+       case -257:
+           vs->has_pointer_type_change = 1;
+           break;
        default:
            break;
        }
     }
+
+    check_pointer_type_change(vs, kbd_mouse_is_absolute());
 }
 
 static int compute_nbits(unsigned int val)
@@ -1371,9 +1395,17 @@ static void vnc_listen_read(void *opaque)
     }
 }
 
-int vnc_display_init(DisplayState *ds, int display, int find_unused, struct sockaddr_in *addr)
+extern int parse_host_port(struct sockaddr_in *saddr, const char *str);
+
+int vnc_display_init(DisplayState *ds, const char *arg, int find_unused, struct sockaddr_in *iaddr)
 {
+    struct sockaddr *addr;
+#ifndef _WIN32
+    struct sockaddr_un uaddr;
+#endif
     int reuse_addr, ret;
+    socklen_t addrlen;
+    const char *p;
     VncState *vs;
 
     vs = qemu_mallocz(sizeof(VncState));
@@ -1381,11 +1413,14 @@ int vnc_display_init(DisplayState *ds, int display, int find_unused, struct sock
        exit(1);
 
     ds->opaque = vs;
+    vnc_state = vs;
+    vs->display = arg;
 
     vs->lsock = -1;
     vs->csock = -1;
     vs->depth = 4;
-    vs->numlock = 0;
+    vs->last_x = -1;
+    vs->last_y = -1;
 
     vs->ds = ds;
 
@@ -1396,28 +1431,64 @@ int vnc_display_init(DisplayState *ds, int display, int find_unused, struct sock
     if (!vs->kbd_layout)
        exit(1);
 
-    vs->lsock = socket(PF_INET, SOCK_STREAM, 0);
-    if (vs->lsock == -1) {
-       fprintf(stderr, "Could not create socket\n");
-       exit(1);
-    }
+    vs->ds->data = NULL;
+    vs->ds->dpy_update = vnc_dpy_update;
+    vs->ds->dpy_resize = vnc_dpy_resize;
+    vs->ds->dpy_refresh = vnc_dpy_refresh;
 
-    reuse_addr = 1;
-    ret = setsockopt(vs->lsock, SOL_SOCKET, SO_REUSEADDR,
-                    (const char *)&reuse_addr, sizeof(reuse_addr));
-    if (ret == -1) {
-       fprintf(stderr, "setsockopt() failed\n");
-       exit(1);
-    }
+    vnc_dpy_resize(vs->ds, 640, 400);
+
+    if (arg == NULL)
+       arg = "localhost:0";
+    
+#ifndef _WIN32
+    if (strstart(arg, "unix:", &p)) {
+       addr = (struct sockaddr *)&uaddr;
+       addrlen = sizeof(uaddr);
+
+       vs->lsock = socket(PF_UNIX, SOCK_STREAM, 0);
+       if (vs->lsock == -1) {
+           fprintf(stderr, "Could not create socket\n");
+           exit(1);
+       }
+
+       uaddr.sun_family = AF_UNIX;
+       memset(uaddr.sun_path, 0, 108);
+       snprintf(uaddr.sun_path, 108, "%s", p);
+
+       unlink(uaddr.sun_path);
+    } else
+#endif
+    {
+       addr = (struct sockaddr *)iaddr;
+       addrlen = sizeof(*iaddr);
+
+       vs->lsock = socket(PF_INET, SOCK_STREAM, 0);
+       if (vs->lsock == -1) {
+           fprintf(stderr, "Could not create socket\n");
+           exit(1);
+       }
+
+       if (parse_host_port(iaddr, arg) < 0) {
+           fprintf(stderr, "Could not parse VNC address\n");
+           exit(1);
+       }
+           
+       iaddr->sin_port = htons(ntohs(iaddr->sin_port) + 5900);
 
- retry:
-    addr->sin_family = AF_INET;
-    addr->sin_port = htons(5900 + display);
+       reuse_addr = 1;
+       ret = setsockopt(vs->lsock, SOL_SOCKET, SO_REUSEADDR,
+                        (const char *)&reuse_addr, sizeof(reuse_addr));
+       if (ret == -1) {
+           fprintf(stderr, "setsockopt() failed\n");
+           exit(1);
+       }
+    }
 
-    if (bind(vs->lsock, (struct sockaddr *)addr, sizeof(struct sockaddr_in)) == -1) {
+    while (bind(vs->lsock, addr, addrlen) == -1) {
        if (find_unused && errno == EADDRINUSE) {
-           display++;
-           goto retry;
+           iaddr->sin_port = htons(ntohs(iaddr->sin_port) + 1);
+           continue;
        }
        fprintf(stderr, "bind() failed\n");
        exit(1);
@@ -1428,19 +1499,12 @@ int vnc_display_init(DisplayState *ds, int display, int find_unused, struct sock
        exit(1);
     }
 
-    ret = qemu_set_fd_handler2(vs->lsock, vnc_listen_poll, vnc_listen_read,
-                              NULL, vs);
-    if (ret == -1)
+    ret = qemu_set_fd_handler2(vs->lsock, vnc_listen_poll, vnc_listen_read, NULL, vs);
+    if (ret == -1) {
        exit(1);
+    }
 
-    vs->ds->data = NULL;
-    vs->ds->dpy_update = vnc_dpy_update;
-    vs->ds->dpy_resize = vnc_dpy_resize;
-    vs->ds->dpy_refresh = vnc_dpy_refresh;
-
-    vnc_dpy_resize(vs->ds, 640, 400);
-
-    return display;
+    return ntohs(iaddr->sin_port);
 }
 
 int vnc_start_viewer(int port)
index 9c6c05f8cfbf47a7a93f68866f85c3130b0b3050..099b18c7a484340f1ca875882c6857401dbfdaa2 100644 (file)
@@ -232,19 +232,6 @@ static name2keysym_t name2keysym[]={
 {"Home", 0xff50},      /* XK_Home */
 {"End", 0xff57},       /* XK_End */
 {"Scroll_Lock", 0xff14}, /* XK_Scroll_Lock */
-{"KP_Home", 0xff95},
-{"KP_Left", 0xff96},
-{"KP_Up", 0xff97},
-{"KP_Right", 0xff98},
-{"KP_Down", 0xff99},
-{"KP_Prior", 0xff9a},
-{"KP_Page_Up", 0xff9a},
-{"KP_Next", 0xff9b},
-{"KP_Page_Down", 0xff9b},
-{"KP_End", 0xff9c},
-{"KP_Begin", 0xff9d},
-{"KP_Insert", 0xff9e},
-{"KP_Delete", 0xff9f},
 {"F1", 0xffbe},        /* XK_F1 */
 {"F2", 0xffbf},        /* XK_F2 */
 {"F3", 0xffc0},        /* XK_F3 */
@@ -272,7 +259,6 @@ static name2keysym_t name2keysym[]={
 {"KP_8", 0xffb8},      /* XK_KP_8 */
 {"KP_9", 0xffb9},      /* XK_KP_9 */
 {"KP_Add", 0xffab},    /* XK_KP_Add */
-{"KP_Separator", 0xffac},/* XK_KP_Separator */
 {"KP_Decimal", 0xffae},  /* XK_KP_Decimal */
 {"KP_Divide", 0xffaf},   /* XK_KP_Divide */
 {"KP_Enter", 0xff8d},    /* XK_KP_Enter */
index 5d34074a65817d8e27b8c70a56754eb2aa873ca8..3d894cd574a990de11bb3596e59b8712e109577a 100644 (file)
@@ -119,7 +119,7 @@ static void CONCAT(send_hextile_tile_, NAME)(VncState *vs,
        for (j = 0; j < h; j++) {
            int has_color = 0;
            int min_x = -1;
-           pixel_t color = 0;
+           pixel_t color = 0; /* shut up gcc */
 
            for (i = 0; i < w; i++) {
                if (!has_color) {
diff --git a/tools/ioemu/x_keymap.c b/tools/ioemu/x_keymap.c
new file mode 100644 (file)
index 0000000..9f72fc3
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * QEMU SDL display driver
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+static const uint8_t x_keycode_to_pc_keycode[115] = {
+   0xc7,      /*  97  Home   */
+   0xc8,      /*  98  Up     */
+   0xc9,      /*  99  PgUp   */
+   0xcb,      /* 100  Left   */
+   0x4c,        /* 101  KP-5   */
+   0xcd,      /* 102  Right  */
+   0xcf,      /* 103  End    */
+   0xd0,      /* 104  Down   */
+   0xd1,      /* 105  PgDn   */
+   0xd2,      /* 106  Ins    */
+   0xd3,      /* 107  Del    */
+   0x9c,      /* 108  Enter  */
+   0x9d,      /* 109  Ctrl-R */
+   0x0,       /* 110  Pause  */
+   0xb7,      /* 111  Print  */
+   0xb5,      /* 112  Divide */
+   0xb8,      /* 113  Alt-R  */
+   0xc6,      /* 114  Break  */
+   0x0,         /* 115 */
+   0x0,         /* 116 */
+   0x0,         /* 117 */
+   0x0,         /* 118 */
+   0x0,         /* 119 */
+   0x0,         /* 120 */
+   0x0,         /* 121 */
+   0x0,         /* 122 */
+   0x0,         /* 123 */
+   0x0,         /* 124 */
+   0x0,         /* 125 */
+   0x0,         /* 126 */
+   0x0,         /* 127 */
+   0x0,         /* 128 */
+   0x79,         /* 129 Henkan */
+   0x0,         /* 130 */
+   0x7b,         /* 131 Muhenkan */
+   0x0,         /* 132 */
+   0x7d,         /* 133 Yen */
+   0x0,         /* 134 */
+   0x0,         /* 135 */
+   0x47,         /* 136 KP_7 */
+   0x48,         /* 137 KP_8 */
+   0x49,         /* 138 KP_9 */
+   0x4b,         /* 139 KP_4 */
+   0x4c,         /* 140 KP_5 */
+   0x4d,         /* 141 KP_6 */
+   0x4f,         /* 142 KP_1 */
+   0x50,         /* 143 KP_2 */
+   0x51,         /* 144 KP_3 */
+   0x52,         /* 145 KP_0 */
+   0x53,         /* 146 KP_. */
+   0x47,         /* 147 KP_HOME */
+   0x48,         /* 148 KP_UP */
+   0x49,         /* 149 KP_PgUp */
+   0x4b,         /* 150 KP_Left */
+   0x4c,         /* 151 KP_ */
+   0x4d,         /* 152 KP_Right */
+   0x4f,         /* 153 KP_End */
+   0x50,         /* 154 KP_Down */
+   0x51,         /* 155 KP_PgDn */
+   0x52,         /* 156 KP_Ins */
+   0x53,         /* 157 KP_Del */
+   0x0,         /* 158 */
+   0x0,         /* 159 */
+   0x0,         /* 160 */
+   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,         /* 170 */
+   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,         /* 180 */
+   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,         /* 190 */
+   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,         /* 200 */
+   0x0,         /* 201 */
+   0x0,         /* 202 */
+   0x0,         /* 203 */
+   0x0,         /* 204 */
+   0x0,         /* 205 */
+   0x0,         /* 206 */
+   0x0,         /* 207 */
+   0x70,         /* 208 Hiragana_Katakana */
+   0x0,         /* 209 */
+   0x0,         /* 210 */
+   0x73,         /* 211 backslash */
+};
+
+uint8_t _translate_keycode(const int key)
+{
+       return x_keycode_to_pc_keycode[key];
+}